<?php

declare(strict_types=1);

namespace App\Console\Commands;

use App\Services\Sitemaps\SitemapBuildService;
use App\Services\Sitemaps\SitemapReleaseManager;
use App\Services\Sitemaps\SitemapReleaseValidator;
use App\Services\Sitemaps\SitemapValidationService;
use Illuminate\Console\Command;

final class ValidateSitemapsCommand extends Command
{
    protected $signature = 'skinbase:sitemaps:validate
        {--only=* : Limit validation to one or more sitemap families}
        {--release= : Validate a specific sitemap release}
        {--active : Validate the active published sitemap release when available}';

    protected $description = 'Validate sitemap XML, shard integrity, and public URL safety.';

    public function handle(SitemapValidationService $validation, SitemapBuildService $build, SitemapReleaseManager $releases, SitemapReleaseValidator $releaseValidator): int
    {
        $startedAt = microtime(true);
        $families = $this->selectedFamilies($build);
        $releaseId = ($value = $this->option('release')) !== null && trim((string) $value) !== ''
            ? trim((string) $value)
            : ((bool) $this->option('active') ? $releases->activeReleaseId() : $releases->activeReleaseId());

        if (is_string($releaseId) && $releaseId !== '') {
            $report = $releaseValidator->validate($releaseId);

            foreach ((array) ($report['families'] ?? []) as $familyReport) {
                $this->line(sprintf(
                    'Family [%s]: documents=%d urls=%d shards=%d',
                    (string) $familyReport['family'],
                    (int) $familyReport['documents'],
                    (int) $familyReport['url_count'],
                    (int) $familyReport['shard_count'],
                ));

                foreach ((array) ($familyReport['warnings'] ?? []) as $warning) {
                    $this->warn(' - ' . $warning);
                }

                foreach ((array) ($familyReport['errors'] ?? []) as $error) {
                    $this->error(' - ' . $error);
                }
            }

            $this->info(sprintf(
                'Sitemap release validation finished in %.2fs. release=%s families=%d documents=%d urls=%d shards=%d',
                microtime(true) - $startedAt,
                $releaseId,
                (int) data_get($report, 'totals.families', 0),
                (int) data_get($report, 'totals.documents', 0),
                (int) data_get($report, 'totals.urls', 0),
                (int) data_get($report, 'totals.shards', 0),
            ));

            if ((bool) ($report['ok'] ?? false)) {
                $this->info('Sitemap validation passed.');

                return self::SUCCESS;
            }

            return self::FAILURE;
        }

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

            return self::INVALID;
        }

        $report = $validation->validate($families);

        foreach ((array) ($report['index']['errors'] ?? []) as $error) {
            $this->error('Index: ' . $error);
        }

        foreach ((array) ($report['families'] ?? []) as $familyReport) {
            $this->line(sprintf(
                'Family [%s]: documents=%d urls=%d shards=%d',
                (string) $familyReport['family'],
                (int) $familyReport['documents'],
                (int) $familyReport['url_count'],
                (int) $familyReport['shard_count'],
            ));

            foreach ((array) ($familyReport['warnings'] ?? []) as $warning) {
                $this->warn(' - ' . $warning);
            }

            foreach ((array) ($familyReport['errors'] ?? []) as $error) {
                $this->error(' - ' . $error);
            }
        }

        if ((array) ($report['duplicates'] ?? []) !== []) {
            foreach ((array) $report['duplicates'] as $duplicate) {
                $this->error('Duplicate URL detected: ' . $duplicate);
            }
        }

        $this->info(sprintf(
            'Sitemap validation finished in %.2fs. families=%d documents=%d urls=%d shards=%d',
            microtime(true) - $startedAt,
            (int) data_get($report, 'totals.families', 0),
            (int) data_get($report, 'totals.documents', 0),
            (int) data_get($report, 'totals.urls', 0),
            (int) data_get($report, 'totals.shards', 0),
        ));

        if ((bool) ($report['ok'] ?? false)) {
            $this->info('Sitemap validation passed.');

            return self::SUCCESS;
        }

        return self::FAILURE;
    }

    /**
     * @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)));
    }
}