<?php

declare(strict_types=1);

namespace App\Services\Sitemaps;

final class PublishedSitemapResolver
{
    public function __construct(private readonly SitemapReleaseManager $releases)
    {
    }

    /**
     * @return array{content: string, release_id: string, document_name: string}|null
     */
    public function resolveIndex(): ?array
    {
        return $this->resolveDocumentName(SitemapCacheService::INDEX_DOCUMENT);
    }

    /**
     * @return array{content: string, release_id: string, document_name: string}|null
     */
    public function resolveNamed(string $requestedName): ?array
    {
        $manifest = $this->releases->activeManifest();

        if ($manifest === null) {
            return null;
        }

        $documentName = $this->canonicalDocumentName($requestedName, $manifest);

        return $documentName !== null ? $this->resolveDocumentName($documentName) : null;
    }

    private function resolveDocumentName(string $documentName): ?array
    {
        $releaseId = $this->releases->activeReleaseId();

        if ($releaseId === null) {
            return null;
        }

        $content = $this->releases->getDocument($releaseId, $documentName);

        return is_string($content) && $content !== ''
            ? ['content' => $content, 'release_id' => $releaseId, 'document_name' => $documentName]
            : null;
    }

    private function canonicalDocumentName(string $requestedName, array $manifest): ?string
    {
        $documents = (array) ($manifest['documents'] ?? []);

        if (isset($documents[$requestedName])) {
            return $requestedName;
        }

        foreach ((array) ($manifest['families'] ?? []) as $familyName => $family) {
            $entryName = (string) ($family['entry_name'] ?? '');
            if ($requestedName === $familyName && $entryName !== '') {
                return $entryName;
            }

            if (preg_match('/^' . preg_quote((string) $familyName, '/') . '-([0-9]+)$/', $requestedName, $matches)) {
                $number = (int) $matches[1];
                $candidate = sprintf('%s-%04d', $familyName, $number);
                if (in_array($candidate, (array) ($family['shards'] ?? []), true)) {
                    return $candidate;
                }
            }
        }

        return null;
    }
}