<?php

declare(strict_types=1);

final class MyronTemplatePreviewFactory
{
    public function __construct(
        private readonly ?MyronTemplateContentResolver $contentResolver = null,
    ) {
    }

    /**
     * Build a preview-page payload that the canonical renderer can consume.
     *
     * STN-013-001: previews now render the canonical seed defaultContent (resolved by
     * MyronTemplateContentResolver — runtime template first, platform definition
     * fallback) instead of the legacy APO-061 R6 "_previewMode" notes-as-body /
     * [unset]-marker behavior. The dev-helper intro string ("Preview of `template.X`
     * rendered from...") is gone in default mode. To keep the engineering
     * inspection use case alive, callers may pass `$devMode = true` to opt back
     * into notes-as-body rendering for individual section debugging.
     *
     * @param array<string, mixed> $definition
     * @param bool $devMode When true, restores the legacy notes-as-body / [unset] preview
     *                      behavior for engineering inspection. Default false (operator-facing).
     * @return array<string, mixed>
     */
    public function buildPreviewPage(array $definition, bool $devMode = false): array
    {
        $templateId = trim((string) ($definition['id'] ?? 'template.preview'));
        $bundleId = trim((string) ($definition['bundleId'] ?? 'site-type.preview'));
        $title = trim((string) (($definition['pageTitle'] ?? '') ?: ($definition['name'] ?? '') ?: $templateId));
        $sections = MyronTemplateDefinitionRepository::bodySectionsForRecord($definition);
        $chrome = MyronTemplateDefinitionRepository::chromeForTemplateRecord($definition);
        $headerCapabilities = MyronTemplateDefinitionRepository::headerCapabilitiesForTemplateRecord($definition, $chrome);

        // Resolve canonical seed defaultContent. Falls through to empty if no seed
        // exists at any layer; in that case the renderer's per-component placeholder
        // logic is responsible for rendering deterministic empty-state markup.
        $defaultContent = $this->contentResolver !== null
            ? $this->contentResolver->resolveDefaultContent($templateId, $devMode === false)
            : (is_array($definition['defaultContent'] ?? null) ? $definition['defaultContent'] : []);

        $pageContent = $this->contentResolver !== null
            ? $this->contentResolver->resolvePageLevelContent($templateId, $devMode === false)
            : [
                'eyebrow' => '',
                'headline' => $title,
                'intro' => '',
                'body' => '',
                'ctaLabel' => $this->ctaLabel($templateId, $bundleId),
                'ctaHref' => $this->ctaHref($templateId, $bundleId),
            ];
        // Guarantee a non-empty CTA in dev mode for legacy renderer expectations.
        if (($pageContent['ctaLabel'] ?? '') === '') {
            $pageContent['ctaLabel'] = $this->ctaLabel($templateId, $bundleId);
        }
        if (($pageContent['ctaHref'] ?? '') === '') {
            $pageContent['ctaHref'] = $this->ctaHref($templateId, $bundleId);
        }
        // Section-keyed content from defaultContent flows alongside the flat fields so
        // the renderer can resolve per-section content via myronSectionContentForInstance.
        $defaultSections = is_array($defaultContent['sections'] ?? null) ? $defaultContent['sections'] : [];
        if ($defaultSections !== []) {
            $pageContent['_schemaVersion'] = 2;
            $pageContent['sections'] = $defaultSections;
        }

        // Section payloads. In dev mode, each section gets _previewMode so the renderer
        // emits notes-as-body / [unset] markers (engineering inspection only). In normal
        // mode the section flows through unchanged and the renderer falls back to the
        // canonical content + per-component placeholders.
        $previewSections = [];
        foreach ($sections as $section) {
            if (!is_array($section)) {
                continue;
            }
            if ($devMode) {
                $section['_previewMode'] = true;
            }
            $previewSections[] = $section;
        }

        return [
            'template_key' => myronNormalizeSlug(str_replace(['template.', '.v1'], ['', ''], $templateId)),
            'title' => $title,
            'version_title' => $title,
            'source_template_id' => $templateId,
            'source_bundle_id' => $bundleId,
            'preview_mode' => true,
            'content' => $pageContent,
            'template_schema' => [
                'sourceTemplateId' => $templateId,
                'sourceBundleId' => $bundleId,
                'chrome' => $chrome,
                'headerCapabilities' => $headerCapabilities,
                'previewMode' => true,
                'devMode' => $devMode,
                'defaultContent' => $defaultContent,
                'bridge' => $this->bridgeMetadataForDefinition($definition, count($previewSections)),
                'sections' => $previewSections,
            ],
        ];
    }

    /**
     * @return array<string, mixed>
     */
    public function buildFallbackPage(string $templateId): array
    {
        $id = trim($templateId) !== '' ? trim($templateId) : 'template.preview.missing';

        return [
            'template_key' => myronNormalizeSlug($id),
            'title' => 'Template preview unavailable',
            'version_title' => 'Template preview unavailable',
            'source_template_id' => $id,
            'source_bundle_id' => 'site-type.preview',
            'content' => [
                'eyebrow' => 'Template preview',
                'headline' => 'Template preview unavailable',
                'intro' => 'The requested template could not be resolved from the definition registry.',
                'body' => 'Choose another template from the manager list.',
                'ctaLabel' => 'Back to templates',
                'ctaHref' => '#',
            ],
            'template_schema' => [
                'sourceTemplateId' => $id,
                'sourceBundleId' => 'site-type.preview',
                'chrome' => [
                    'header' => ['inherit' => 'global', 'variant' => ''],
                    'footer' => ['inherit' => 'global', 'variant' => ''],
                    'headerCapabilities' => [],
                ],
                'headerCapabilities' => [],
                'bridge' => [
                    'normalizedBodySections' => true,
                    'legacyChromeSectionCount' => 0,
                    'bodySectionCount' => 1,
                ],
                'sections' => [
                    ['componentId' => 'section-band', 'variant' => 'preview-unavailable'],
                ],
            ],
        ];
    }

    /**
     * @param array<string, mixed> $definition
     * @return array{normalizedBodySections:bool,legacyChromeSectionCount:int,bodySectionCount:int}
     */
    private function bridgeMetadataForDefinition(array $definition, int $bodySectionCount): array
    {
        $chromeCount = 0;
        foreach (is_array($definition['sections'] ?? null) ? $definition['sections'] : [] as $section) {
            if (!is_array($section)) {
                continue;
            }

            if (in_array(trim((string) ($section['componentId'] ?? '')), ['header', 'footer'], true)) {
                $chromeCount++;
            }
        }

        return [
            'normalizedBodySections' => true,
            'legacyChromeSectionCount' => $chromeCount,
            'bodySectionCount' => $bodySectionCount,
        ];
    }

    private function ctaLabel(string $templateId, string $bundleId): string
    {
        if ($bundleId === 'site-type.ecom') {
            return str_contains($templateId, '.checkout.') ? 'Place test order' : 'Shop now';
        }
        if ($bundleId === 'site-type.bkg') {
            return 'Book now';
        }
        if ($bundleId === 'site-type.saas') {
            return 'Start Free Trial';
        }
        if ($bundleId === 'site-type.mkt') {
            return str_contains($templateId, '.sales') ? 'Checkout' : 'Join the list';
        }

        return str_contains($templateId, '.contact.') ? 'Send message' : 'Continue';
    }

    private function ctaHref(string $templateId, string $bundleId): string
    {
        if ($bundleId === 'site-type.ecom') {
            return str_contains($templateId, '.checkout.') ? '/checkout' : '/shop';
        }
        if ($bundleId === 'site-type.bkg') {
            return '/reservation';
        }
        if ($bundleId === 'site-type.saas') {
            return '/signup';
        }
        if ($bundleId === 'site-type.mkt') {
            return str_contains($templateId, '.sales') ? '/checkout' : '/squeeze';
        }

        return str_contains($templateId, '.contact.') ? '/contact' : '/';
    }
}
