<?php

declare(strict_types=1);

namespace App\Console\Commands;

use App\Jobs\Sitemaps\BuildSitemapReleaseJob;
use App\Services\Sitemaps\SitemapBuildService;
use App\Services\Sitemaps\SitemapPublishService;
use Illuminate\Console\Command;

final class BuildSitemapsCommand extends Command
{
    protected $signature = 'skinbase:sitemaps:build
        {--only=* : Limit the build to one or more sitemap families}
        {--release= : Override the generated release id}
        {--shards : Show per-shard output in the command report}
        {--queue : Dispatch the release build to the queue}
        {--force : Accepted for backward compatibility; release builds are always fresh}
        {--clear : Accepted for backward compatibility; release builds are isolated}
        {--dry-run : Build a release artifact set without activating it}';

    protected $description = 'Build a versioned sitemap release artifact set.';

    public function handle(SitemapBuildService $build, SitemapPublishService $publish): int
    {
        $startedAt = microtime(true);
        $families = $this->selectedFamilies($build);
        $releaseId = ($value = $this->option('release')) !== null && trim((string) $value) !== '' ? trim((string) $value) : null;

        if ($families === []) {
            $this->error('No valid sitemap families were selected.');

            return self::INVALID;
        }

        $showShards = (bool) $this->option('shards');

        if ((bool) $this->option('queue')) {
            BuildSitemapReleaseJob::dispatch($families, $releaseId);
            $this->info('Queued sitemap release build' . ($releaseId !== null ? ' for [' . $releaseId . '].' : '.'));

            return self::SUCCESS;
        }

        try {
            $manifest = $publish->buildRelease($families, $releaseId);
        } catch (\Throwable $exception) {
            $this->error($exception->getMessage());

            return self::FAILURE;
        }

        $totalUrls = 0;
        $totalDocuments = 0;

        foreach ($families as $family) {
            $names = (array) data_get($manifest, 'families.' . $family . '.documents', []);
            $familyUrls = 0;

            if (! $showShards) {
                $this->line('Building family [' . $family . '] with ' . count($names) . ' document(s).');
            }

            foreach ($names as $name) {
                $documentType = str_ends_with((string) $name, '-index') ? 'index' : ((string) $family === (string) config('sitemaps.news.google_variant_name', 'news-google') ? 'google-news' : 'urlset');
                $familyUrls += (int) data_get($manifest, 'families.' . $family . '.url_count', 0);
                $totalUrls += (int) data_get($manifest, 'families.' . $family . '.url_count', 0);
                $totalDocuments++;

                if ($showShards || ! str_contains((string) $name, '-000')) {
                    $this->line(sprintf(
                        ' - %s [%s]',
                        $name,
                        $documentType,
                    ));
                }
            }

            $this->info(sprintf('Family [%s] complete: urls=%d documents=%d', $family, (int) data_get($manifest, 'families.' . $family . '.url_count', 0), count($names)));
        }
        $totalDocuments++;

        $this->info(sprintf(
            'Sitemap release [%s] complete: families=%d documents=%d urls=%d status=%s duration=%.2fs',
            (string) $manifest['release_id'],
            (int) data_get($manifest, 'totals.families', 0),
            (int) data_get($manifest, 'totals.documents', 0),
            (int) data_get($manifest, 'totals.urls', 0),
            (string) ($manifest['status'] ?? 'built'),
            microtime(true) - $startedAt,
        ));
        $this->line('Sitemap index complete');

        return self::SUCCESS;
    }

    /**
     * @return list<string>
     */
    private function selectedFamilies(SitemapBuildService $build): array
    {
        $only = [];

        foreach ((array) $this->option('only') as $value) {
            foreach (explode(',', (string) $value) as $family) {
                $normalized = trim($family);
                if ($normalized !== '') {
                    $only[] = $normalized;
                }
            }
        }

        $enabled = $build->enabledFamilies();

        if ($only === []) {
            return $enabled;
        }

        return array_values(array_filter($enabled, fn (string $family): bool => in_array($family, $only, true)));
    }
}