<?php

declare(strict_types=1);

final class MyronPublicHeaderContextResolver
{
    public function __construct(
        private readonly MyronContentRepository $content,
        private readonly MyronNavigationDesignRepository $designs,
        private readonly MyronTemplateChromeAssignmentRepository $assignments,
        private readonly MyronBundleActivationRepository $bundles,
        private readonly MyronFileRepository $files,
    ) {
    }

    /**
     * @param array<string, mixed>|null $page
     * @param list<array<string, mixed>> $primaryNavigation
     * @return array<string, mixed>
     */
    public function resolve(?array $page, string $resolvedPath, array $primaryNavigation): array
    {
        $path = $page === null ? myronNormalizePath($resolvedPath) : myronNormalizePath((string) ($page['path'] ?? $resolvedPath));
        $schema = is_array($page['template_schema'] ?? null) ? $page['template_schema'] : [];
        $chrome = is_array($schema['chrome'] ?? null) ? $schema['chrome'] : [];
        $headerChrome = is_array($chrome['header'] ?? null) ? $chrome['header'] : [];
        $templateKey = $this->templateScopeKey($page, $schema);
        $assignment = $templateKey !== '' ? $this->assignments->getForTemplate($templateKey) : null;
        $assignedNavigationId = is_array($assignment) ? trim((string) ($assignment['navigation_design_id'] ?? '')) : '';
        $navigationDesign = $assignedNavigationId !== ''
            ? $this->designs->getById($assignedNavigationId)
            : $this->designs->getDefault();
        $settings = is_array($navigationDesign) ? $navigationDesign : $this->designs->getDefault();
        $siteLogoLightUrl = myronSiteLogoLightUrl();
        $siteLogoDarkUrl = myronSiteLogoDarkUrl();
        if ($siteLogoLightUrl === '' && $siteLogoDarkUrl !== '') {
            $siteLogoLightUrl = $siteLogoDarkUrl;
        }
        if ($siteLogoDarkUrl === '' && $siteLogoLightUrl !== '') {
            $siteLogoDarkUrl = $siteLogoLightUrl;
        }
        $siteLogoAlt = myronSiteLogoAlt();
        $siteLogoLightMeta = $this->logoMetadataByUrl($siteLogoLightUrl, $siteLogoAlt);
        $siteLogoDarkMeta = $this->logoMetadataByUrl($siteLogoDarkUrl, $siteLogoAlt);
        $variant = $this->variantFromChrome((string) ($headerChrome['variant'] ?? ''));
        $utilityEnabled = $settings['utility_actions_display'] !== 'hide';
        $actions = $this->activeHeaderActions();
        $creativeSettings = myronSiteSettingsRepository()->creativeSettings();
        $defaultFeatures = [
            'brand' => true,
            'primaryMenu' => true,
            'utilityActions' => $utilityEnabled && ($settings['utility_actions_display'] === 'show' || $actions !== []),
        ];

        $context = [
            'variant' => $page === null ? 'minimal' : $variant,
            'settings' => $settings,
            'brand' => [
                'title' => myronSiteTitle(),
                'subtitle' => $settings['brand_subtitle'],
                'display' => $settings['brand_display'],
                'logo_url' => $siteLogoLightUrl,
                'logo_light_url' => $siteLogoLightUrl,
                'logo_dark_url' => $siteLogoDarkUrl,
                'logo_alt' => $siteLogoAlt,
                'logo_light_alt' => $siteLogoLightMeta['alt'],
                'logo_dark_alt' => $siteLogoDarkMeta['alt'],
                'logo_light_width' => $siteLogoLightMeta['width'],
                'logo_light_height' => $siteLogoLightMeta['height'],
                'logo_dark_width' => $siteLogoDarkMeta['width'],
                'logo_dark_height' => $siteLogoDarkMeta['height'],
            ],
            'primaryNavigation' => $primaryNavigation,
            'utilityActions' => $actions,
            'features' => $defaultFeatures,
            'defaultFeatures' => $defaultFeatures,
            'scope' => [
                'pagePath' => $path,
                'templateKey' => $templateKey,
                'navigationDesignId' => (string) ($settings['id'] ?? ''),
                'chromeVariant' => (string) ($headerChrome['variant'] ?? ''),
                'capabilities' => array_values(array_map('strval', is_array($schema['headerCapabilities'] ?? null) ? $schema['headerCapabilities'] : [])),
            ],
            'creative' => [
                'navStyle' => $creativeSettings['navStyle'],
                'navParams' => $creativeSettings['navParams'],
            ],
        ];

        $this->applyVariantDefaults($context);
        if ((string) ($context['variant'] ?? '') === 'hidden') {
            $this->applyVariantDefaults($context);
        }

        return $context;
    }

    /**
     */
    /**
     * @return array{alt:string,width:int,height:int}
     */
    private function logoMetadataByUrl(string $url, string $fallback): array
    {
        $metadata = [
            'alt' => $fallback,
            'width' => 0,
            'height' => 0,
        ];
        $fileId = $this->fileIdFromStreamUrl($url);
        if ($fileId === '') {
            return $metadata;
        }

        $file = $this->files->getFileById($fileId);
        if (!is_array($file) || !(bool) ($file['is_image'] ?? false)) {
            return $metadata;
        }

        $alt = trim((string) ($file['alt_text'] ?? ''));
        if ($alt === '') {
            $alt = trim((string) (($file['title'] ?? '') ?: ($file['original_filename'] ?? '')));
        }

        $metadata['alt'] = $alt !== '' ? $alt : $fallback;
        $metadata['width'] = max(0, (int) ($file['image_width'] ?? 0));
        $metadata['height'] = max(0, (int) ($file['image_height'] ?? 0));

        return $metadata;
    }

    private function fileIdFromStreamUrl(string $url): string
    {
        if (trim($url) === '') {
            return '';
        }

        $query = parse_url($url, PHP_URL_QUERY);
        if (!is_string($query) && str_contains($url, '?')) {
            $query = (string) parse_url('https://myron.local' . $url, PHP_URL_QUERY);
        }
        if (!is_string($query) || $query === '') {
            return '';
        }

        parse_str($query, $params);
        return trim((string) ($params['id'] ?? ''));
    }

    /**
     * @return list<array{label:string,href:string}>
     */
    private function activeHeaderActions(): array
    {
        $bundleIds = [];
        $primaryBundleId = $this->bundles->getPrimaryBundleId();
        if ($primaryBundleId !== null && trim($primaryBundleId) !== '') {
            $bundleIds[] = trim($primaryBundleId);
        }
        foreach ($this->bundles->listActiveBundles() as $state) {
            $bundleId = trim((string) ($state['bundle_id'] ?? ''));
            if ($bundleId !== '' && !in_array($bundleId, $bundleIds, true)) {
                $bundleIds[] = $bundleId;
            }
        }

        foreach ($bundleIds as $bundleId) {
            foreach ($this->content->listBundleSeedRecords($bundleId) as $record) {
                $payload = is_array($record['payload'] ?? null) ? $record['payload'] : [];
                if ((string) ($payload['placement'] ?? '') !== 'headerRight') {
                    continue;
                }
                $actions = $this->normalizeActions(is_array($payload['actions'] ?? null) ? $payload['actions'] : []);
                if ($actions !== []) {
                    return $actions;
                }
            }
        }

        return [];
    }

    /**
     * @param list<mixed> $actions
     * @return list<array{label:string,href:string}>
     */
    private function normalizeActions(array $actions): array
    {
        $normalized = [];
        foreach ($actions as $action) {
            if (!is_array($action)) {
                continue;
            }
            $label = trim((string) ($action['label'] ?? ''));
            $href = trim((string) ($action['href'] ?? ''));
            if ($label === '' || $href === '') {
                continue;
            }
            $normalized[] = ['label' => $label, 'href' => $href];
        }

        return $normalized;
    }

    /**
     * @param array<string, mixed>|null $page
     * @param array<string, mixed> $schema
     */
    private function templateScopeKey(?array $page, array $schema): string
    {
        foreach ([
            $schema['sourceTemplateId'] ?? '',
            $page['source_template_id'] ?? '',
            $page['template_source_template_id'] ?? '',
            $page['template_key'] ?? '',
        ] as $candidate) {
            $key = trim((string) $candidate);
            if ($key !== '') {
                return $key;
            }
        }

        return '';
    }

    private function variantFromChrome(string $chromeVariant): string
    {
        $normalized = myronNormalizeSlug($chromeVariant);
        if ($normalized === 'hidden') {
            return 'hidden';
        }
        if ($normalized === 'minimal' || str_contains($normalized, 'minimal') || str_contains($normalized, 'campaign')) {
            return 'minimal';
        }

        return 'full';
    }

    /**
     * @param array<string, mixed> $context
     */
    private function applyVariantDefaults(array &$context): void
    {
        $variant = (string) ($context['variant'] ?? 'full');
        if ($variant === 'hidden') {
            $context['features']['brand'] = false;
            $context['features']['primaryMenu'] = false;
            $context['features']['utilityActions'] = false;
            return;
        }

        if ($variant === 'minimal') {
            $context['features']['primaryMenu'] = false;
            $context['features']['utilityActions'] = false;
        }
    }

    /**
     * @param array<string, mixed> $context
     * @param array<string, mixed>|null $override
     */
    private function applyOverride(array &$context, ?array $override): void
    {
        if (!is_array($override)) {
            return;
        }

        $variant = (string) ($override['header_variant'] ?? 'inherit');
        if ($variant !== 'inherit') {
            $context['variant'] = $variant;
            if ($variant === 'full') {
                $context['features'] = is_array($context['defaultFeatures'] ?? null) ? $context['defaultFeatures'] : $context['features'];
            } elseif ($variant === 'minimal') {
                $context['features']['brand'] = true;
                $context['features']['primaryMenu'] = false;
                $context['features']['utilityActions'] = false;
            } elseif ($variant === 'hidden') {
                $context['features']['brand'] = false;
                $context['features']['primaryMenu'] = false;
                $context['features']['utilityActions'] = false;
            }
        }

        foreach ([
            'primary_menu_visibility' => 'primaryMenu',
            'utility_actions_visibility' => 'utilityActions',
            'brand_visibility' => 'brand',
        ] as $overrideKey => $featureKey) {
            $visibility = (string) ($override[$overrideKey] ?? 'inherit');
            if ($visibility === 'show') {
                $context['features'][$featureKey] = true;
            } elseif ($visibility === 'hide') {
                $context['features'][$featureKey] = false;
            }
        }
    }
}
