<?php

declare(strict_types=1);

if (!defined('MYRON_PUBLIC_SITE_REQUEST')) {
    define('MYRON_PUBLIC_SITE_REQUEST', true);
}

require_once dirname(__DIR__, 2) . '/system/bootstrap.php';

myronPublicRenderProfiler()->mark('route_start');
$repository = myronContentRepository();
myronPublicRenderProfiler()->mark('repository_ready');

$requestUri = (string) ($_SERVER['REQUEST_URI'] ?? '/');
$basePath = myronPublicBasePath();
$resolvedPath = myronResolvePublicRequestPath($requestUri);

$publicMode = (string) (myronSiteSettings()['public_mode'] ?? 'off');
if ($publicMode === 'coming_soon' || $publicMode === 'maintenance') {
    $bypassUser = myronCurrentUser();
    if (!is_array($bypassUser) || !myronUserCanAccessAdministration($bypassUser)) {
        while (ob_get_level() > 0) {
            ob_end_clean();
        }
        http_response_code($publicMode === 'maintenance' ? 503 : 200);
        header('Content-Type: text/html; charset=utf-8');
        header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
        header('X-Robots-Tag: noindex, nofollow');
        if ($publicMode === 'maintenance') {
            header('Retry-After: 3600');
        }
        $mode = $publicMode;
        require dirname(__DIR__) . '/templates/public-site-mode.php';
        exit;
    }
}

if ($resolvedPath === '/media/files/stream') {
    require __DIR__ . '/media-file-stream.php';
    exit;
}

if ($resolvedPath === '/media/interactions/stream') {
    myronCustomCssRepository()->streamInteractionLibrary((string) ($_GET['file'] ?? ''));
    exit;
}

if ($resolvedPath === '/media/fonts/stream') {
    myronCustomCssRepository()->streamFontFile((string) ($_GET['file'] ?? ''));
    exit;
}

$resolvedPath = myronModuleRegistry()->filterPublicPath($resolvedPath, ['requestUri' => $requestUri]);

foreach (myronModuleRegistry()->publicHandlers() as $modulePublicHandler) {
    if ($modulePublicHandler($resolvedPath, $requestUri)) {
        exit;
    }
}

$modulePage = myronModuleRegistry()->resolvePublicPage($resolvedPath, ['requestUri' => $requestUri]);

if (!function_exists('myronSiteEscape')) {
    function myronSiteEscape(string $value): string
    {
        return htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
    }
}

if (!function_exists('myronSiteAsyncStylesheetLink')) {
    function myronSiteAsyncStylesheetLink(string $href): string
    {
        $escapedHref = myronSiteEscape($href);
        return '<link rel="preload" as="style" href="' . $escapedHref . '" onload="this.onload=null;this.rel=\'stylesheet\'">'
            . '<noscript><link rel="stylesheet" href="' . $escapedHref . '"></noscript>';
    }
}

if ($resolvedPath === '/sitemap.xml') {
    header('Content-Type: application/xml; charset=utf-8');
    header('Cache-Control: public, max-age=3600');
    echo myronSitemapGenerator()->generate();
    return;
}

if ($resolvedPath === '/llms.txt') {
    header('Content-Type: text/plain; charset=utf-8');
    header('Cache-Control: public, max-age=3600');
    echo myronLlmsTxtGenerator()->generate();
    return;
}

if ($resolvedPath === '/robots.txt') {
    header('Content-Type: text/plain; charset=utf-8');
    header('Cache-Control: public, max-age=3600');
    echo myronRobotsTxtGenerator()->generate();
    return;
}

$rolePage = null;
if (!is_array($modulePage) && $resolvedPath === '/') {
    $rolePage = myronPageRoleResolver()->resolve('home', '/');
}
if (!is_array($modulePage) && $resolvedPath === '/search') {
    $rolePage = myronPageRoleResolver()->resolve('search', '/search');
    if (is_array($rolePage)) {
        $queryRaw = trim((string) ($_GET['q'] ?? ''));
        $limitInput = (int) ($_GET['limit'] ?? MyronSearchIndexService::DEFAULT_LIMIT);
        $isDevEnv = (string) (getenv('MYRON_APP_ENV') ?: '') === 'local';
        $rolePage['_runtimeData'] = [
            'search' => myronPublicSearchRequestService()->search($queryRaw, $limitInput, $isDevEnv),
        ];
    }
}
if (!is_array($modulePage) && $resolvedPath === '/search' && !is_array($rolePage)) {
    require __DIR__ . '/search.php';
    exit;
}

$page = is_array($modulePage) ? null : (is_array($rolePage) ? $rolePage : $repository->getPublishedPageByPath($resolvedPath));
if ($page === null && !is_array($modulePage)) {
    $redirect = myronDisabledPageRedirectsRepository()->findByPath($resolvedPath);
    if (is_array($redirect)) {
        header('Location: ' . (string) ($redirect['fallback_url'] ?? '/'), true, 302);
        exit;
    }
    $page = myronPageRoleResolver()->resolve('not-found', $resolvedPath);
}
myronPublicRenderProfiler()->mark('page_read');
$navigationByPlacement = $repository->listPublishedMenuNavigationByPlacements(['primary'], ['footer']);
$navigation = $navigationByPlacement['trees']['primary'] ?? [];
$footerNavigation = $navigationByPlacement['flat']['footer'] ?? [];
myronPublicRenderProfiler()->mark('navigation_read');
$headerContext = myronPublicHeaderContextResolver()->resolve($page, $resolvedPath, $navigation);
myronPublicRenderProfiler()->mark('header_context');
$currentUser = myronCurrentUser();
$anonymousPublicRequest = !is_array($currentUser);
$requiresQuizStyles = str_starts_with($resolvedPath, '/quiz/')
    || (is_array($modulePage) && !empty($modulePage['requiresQuizStyles']));
$siteActionLabel = is_array($currentUser) ? 'Manage Site' : 'Login to MyronCMS';
$siteActionTarget = is_array($currentUser)
    ? myronBuildAdminUrl(myronDefaultAuthorizedRoute($currentUser))
    : myronBuildAdminUrl('auth.login');

if (!function_exists('myronResolvePublicAppearanceContext')) {
    /**
     * @param array<string, mixed> $headerSettings
     * @return array{defaultMode:string,systemFollow:bool,policy:string,initialMode:string}
     */
    function myronResolvePublicAppearanceContext(array $headerSettings): array
    {
        $policy = trim((string) ($headerSettings['appearance_mode_policy'] ?? 'auto'));
        if (!in_array($policy, ['auto', 'light', 'dark'], true)) {
            $policy = 'auto';
        }

        $defaultMode = 'light';
        $systemFollow = false;
        try {
            static $resolvedDefinition = null;
            if (!is_array($resolvedDefinition)) {
                $registry = new DesignSystemRegistry();
                $current = $registry->currentDefinition();
                $definition = StyleDefinitionRuntime::loadJson((string) ($current['path'] ?? ''));
                $resolvedDefinition = [
                    'defaultMode' => StyleDefinitionRuntime::resolveDefaultMode($definition),
                    'systemFollow' => (bool) ($definition['settings']['systemFollow'] ?? false),
                ];
            }
            $defaultMode = (string) ($resolvedDefinition['defaultMode'] ?? 'light');
            $systemFollow = (bool) ($resolvedDefinition['systemFollow'] ?? false);
        } catch (Throwable) {
            $defaultMode = 'light';
            $systemFollow = false;
        }

        $initialMode = $policy === 'light' || $policy === 'dark'
            ? $policy
            : ($systemFollow ? '' : $defaultMode);

        return [
            'defaultMode' => $defaultMode,
            'systemFollow' => $systemFollow,
            'policy' => $policy,
            'initialMode' => $initialMode,
        ];
    }
}

if (!function_exists('myronRenderPublicAppearanceBootstrapScript')) {
    function myronRenderPublicAppearanceBootstrapScript(): string
    {
        return <<<'HTML'
  <script>
(function () {
  "use strict";
  var html = document.documentElement;
  function isMode(value) {
    return value === "light" || value === "dark";
  }
  function readStoredMode() {
    try {
      var value = window.localStorage.getItem("myron-appearance") || "";
      return isMode(value) ? value : "";
    } catch (error) {
      return "";
    }
  }
  function systemPrefersDark() {
    return !!(window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches);
  }
  function resolveMode(policy, defaultMode, systemFollow, storedMode) {
    if (policy === "light" || policy === "dark") {
      return policy;
    }
    if (isMode(storedMode)) {
      return storedMode;
    }
    if (systemFollow && systemPrefersDark()) {
      return "dark";
    }
    return isMode(defaultMode) ? defaultMode : "light";
  }
  var policy = html.getAttribute("data-appearance-policy") || "auto";
  var defaultMode = html.getAttribute("data-appearance-default") || "light";
  var systemFollow = html.getAttribute("data-appearance-system-follow") === "true";
  html.setAttribute("data-appearance", resolveMode(policy, defaultMode, systemFollow, readStoredMode()));
})();
  </script>
HTML;
    }
}

if (!function_exists('myronPublicHeaderAssetHref')) {
    function myronPublicHeaderAssetHref(string $basePath, string $href): string
    {
        $trimmed = trim($href);
        if ($trimmed === '') {
            return '';
        }
        if (str_starts_with($trimmed, '#') || preg_match('/^https?:\/\//i', $trimmed) === 1 || str_starts_with($trimmed, '//')) {
            return $trimmed;
        }
        if (str_starts_with($trimmed, '/') && !str_starts_with($trimmed, '//')) {
            return $trimmed;
        }

        $normalizedPath = myronNormalizePath($trimmed);
        $siteRoot = $basePath === '' ? '' : $basePath;
        return ($siteRoot === '' ? '' : $siteRoot) . $normalizedPath;
    }
}

if (!function_exists('myronPublicLogoPreloadLinks')) {
    /**
     * @param array<string, mixed> $headerContext
     * @param array{defaultMode:string,systemFollow:bool,policy:string,initialMode:string} $appearanceContext
     */
    function myronPublicLogoPreloadLinks(array $headerContext, array $appearanceContext, string $basePath): string
    {
        $brand = is_array($headerContext['brand'] ?? null) ? $headerContext['brand'] : [];
        $display = trim((string) ($brand['display'] ?? 'title')) ?: 'title';
        if ($display !== 'logo' && $display !== 'lockup') {
            return '';
        }

        $logoUrl = trim((string) ($brand['logo_url'] ?? ''));
        $lightLogoUrl = trim((string) ($brand['logo_light_url'] ?? '')) ?: $logoUrl;
        $darkLogoUrl = trim((string) ($brand['logo_dark_url'] ?? '')) ?: $logoUrl;
        if ($lightLogoUrl === '' && $darkLogoUrl !== '') {
            $lightLogoUrl = $darkLogoUrl;
        }
        if ($darkLogoUrl === '' && $lightLogoUrl !== '') {
            $darkLogoUrl = $lightLogoUrl;
        }
        if ($lightLogoUrl === '') {
            return '';
        }

        $links = [];
        $append = static function (string $url, string $media = '') use (&$links, $basePath): void {
            $href = myronPublicHeaderAssetHref($basePath, $url);
            if ($href === '' || !str_starts_with($href, '/') || str_starts_with($href, '//') || isset($links[$href . '|' . $media])) {
                return;
            }
            $mediaAttribute = $media === '' ? '' : ' media="' . myronSiteEscape($media) . '"';
            $links[$href . '|' . $media] = '  <link rel="preload" as="image" href="' . myronSiteEscape($href) . '"' . $mediaAttribute . '>';
        };

        if ($lightLogoUrl === $darkLogoUrl) {
            $append($lightLogoUrl);
        } elseif ($appearanceContext['policy'] === 'light' || $appearanceContext['initialMode'] === 'light') {
            $append($lightLogoUrl);
        } elseif ($appearanceContext['policy'] === 'dark' || $appearanceContext['initialMode'] === 'dark') {
            $append($darkLogoUrl);
        } elseif ($appearanceContext['systemFollow']) {
            $append($lightLogoUrl, '(prefers-color-scheme: light)');
            $append($darkLogoUrl, '(prefers-color-scheme: dark)');
        }

        return implode("\n", array_values($links));
    }
}

$appearanceContext = myronResolvePublicAppearanceContext(is_array($headerContext['settings'] ?? null) ? $headerContext['settings'] : []);
$headerCreative = is_array($headerContext['creative'] ?? null) ? $headerContext['creative'] : [];
$headerCreativeNavStyle = myronNormalizeSlug((string) ($headerCreative['navStyle'] ?? ''));
$headerCreativeNeedsRuntime = in_array($headerCreativeNavStyle, ['floating-nav', 'sticky-compact-nav'], true);
$siteCreativeSettings = myronSiteSettingsRepository()->creativeSettings();
$buttonCreativeStyle = myronNormalizeSlug((string) ($siteCreativeSettings['btnStyle'] ?? ''));
$buttonCreativeNeedsRuntime = in_array($buttonCreativeStyle, ['btn-magnetic-follow', 'btn-border-trace'], true);
myronPublicRenderProfiler()->mark('appearance_context');

if (is_array($modulePage) && is_array($modulePage['headMetadata'] ?? null)) {
    $headMetadata = $modulePage['headMetadata'];
} elseif ($page === null) {
    http_response_code(404);
    $headMetadata = myronPublicHeadMetadataResolver()->resolveNotFound();
} else {
    if (($page['_pageRole'] ?? '') === 'not-found') {
        http_response_code(404);
    }
    $headMetadata = myronPublicHeadMetadataResolver()->resolvePublishedPage($page);
}
myronPublicRenderProfiler()->mark('head_metadata');

if (is_array($page)) {
    echo myronPublishedPageHtmlAssembler()->assemble($page, [
        'basePath' => $basePath,
        'requestUri' => $requestUri,
        'resolvedPath' => $resolvedPath,
        'navigation' => $navigation,
        'footerNavigation' => $footerNavigation,
        'headerContext' => $headerContext,
        'appearanceContext' => $appearanceContext,
        'headMetadata' => $headMetadata,
        'currentUser' => $currentUser,
        'headerCreativeNeedsRuntime' => $headerCreativeNeedsRuntime,
        'buttonCreativeNeedsRuntime' => $buttonCreativeNeedsRuntime,
        'channel' => 'public',
    ]);
    return;
}
	?>
<!DOCTYPE html>
<html lang="<?= myronSiteEscape(myronSiteLanguage()) ?>" data-appearance-default="<?= myronSiteEscape($appearanceContext['defaultMode']) ?>" data-appearance-policy="<?= myronSiteEscape($appearanceContext['policy']) ?>" data-appearance-system-follow="<?= $appearanceContext['systemFollow'] ? 'true' : 'false' ?>"<?= $appearanceContext['initialMode'] !== '' ? ' data-appearance="' . myronSiteEscape($appearanceContext['initialMode']) . '"' : '' ?>>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title><?= myronSiteEscape($headMetadata['documentTitle']) ?></title>
  <meta name="description" content="<?= myronSiteEscape($headMetadata['metaDescription']) ?>">
  <?php if ($headMetadata['canonicalUrl'] !== ''): ?>
  <link rel="canonical" href="<?= myronSiteEscape($headMetadata['canonicalUrl']) ?>">
  <?php endif; ?>
  <?php if ($headMetadata['robots'] !== ''): ?>
  <meta name="robots" content="<?= myronSiteEscape($headMetadata['robots']) ?>">
  <?php endif; ?>
  <?php if (!empty($headMetadata['socialEnabled'])): ?>
  <?php $og = is_array($headMetadata['og'] ?? null) ? $headMetadata['og'] : []; ?>
  <?php $twitter = is_array($headMetadata['twitter'] ?? null) ? $headMetadata['twitter'] : []; ?>
  <meta property="og:type" content="<?= myronSiteEscape((string) ($og['type'] ?? 'article')) ?>">
  <meta property="og:title" content="<?= myronSiteEscape((string) ($og['title'] ?? '')) ?>">
  <meta property="og:description" content="<?= myronSiteEscape((string) ($og['description'] ?? '')) ?>">
  <meta property="og:url" content="<?= myronSiteEscape((string) ($og['url'] ?? '')) ?>">
  <?php if (trim((string) ($og['image'] ?? '')) !== ''): ?>
  <meta property="og:image" content="<?= myronSiteEscape((string) $og['image']) ?>">
  <?php endif; ?>
  <meta name="twitter:card" content="<?= myronSiteEscape((string) ($twitter['card'] ?? 'summary_large_image')) ?>">
  <meta name="twitter:title" content="<?= myronSiteEscape((string) ($twitter['title'] ?? '')) ?>">
  <meta name="twitter:description" content="<?= myronSiteEscape((string) ($twitter['description'] ?? '')) ?>">
  <?php if (trim((string) ($twitter['image'] ?? '')) !== ''): ?>
  <meta name="twitter:image" content="<?= myronSiteEscape((string) $twitter['image']) ?>">
  <?php endif; ?>
  <?php endif; ?>
  <?= myronJsonLdService()->renderGlobal(myronSiteSettings()) . "\n" ?>
  <?php if (is_array($page)): ?>
  <?= myronJsonLdService()->renderPage($page, myronSiteSettings()) . "\n" ?>
  <?php endif; ?>
  <?= myronRenderSiteFaviconLink() . "\n" ?>
  <?= myronRenderPublicAppearanceBootstrapScript() . "\n" ?>
  <?= myronPublicLogoPreloadLinks($headerContext, $appearanceContext, $basePath) . "\n" ?>
  <?= myronRenderDefinitionFontHeadTags() . "\n" ?>
  <link rel="stylesheet" href="<?= myronSiteEscape(myronBuildAssetUrl('runtime/css/tokens.css')) ?>">
  <link rel="stylesheet" href="<?= myronSiteEscape(myronBuildAssetUrl('runtime/css/runtime-fonts.css')) ?>">
  <?= myronCustomCssRepository()->renderCustomFontHeadTags() . "\n" ?>
  <link rel="stylesheet" href="<?= myronSiteEscape(myronBuildAssetUrl('runtime/css/runtime-token-overrides.css')) ?>">
  <link rel="stylesheet" href="<?= myronSiteEscape(myronBuildAssetUrl('runtime/css/base.css')) ?>">
  <link rel="stylesheet" href="<?= myronSiteEscape(myronBuildAssetUrl('runtime/css/public-critical.css')) ?>">
  <?php if ($anonymousPublicRequest): ?>
  <?= myronSiteAsyncStylesheetLink(myronBuildAssetUrl('runtime/css/components.min.css')) . "\n" ?>
  <?= myronSiteAsyncStylesheetLink(myronBuildAssetUrl('runtime/css/public-site.min.css')) . "\n" ?>
  <?php if ($requiresQuizStyles): ?>
  <?= myronSiteAsyncStylesheetLink(myronBuildAssetUrl('runtime/css/quiz-public.min.css')) . "\n" ?>
  <?php endif; ?>
  <?php else: ?>
  <link rel="stylesheet" href="<?= myronSiteEscape(myronBuildAssetUrl('runtime/css/components.css')) ?>">
  <link rel="stylesheet" href="<?= myronSiteEscape(myronBuildAssetUrl('runtime/css/public-site.css')) ?>">
  <?php if ($requiresQuizStyles): ?>
  <link rel="stylesheet" href="<?= myronSiteEscape(myronBuildAssetUrl('runtime/css/quiz-public.css')) ?>">
  <?php endif; ?>
  <?php endif; ?>
  <?= myronCustomCssRepository()->renderSiteStyleTag(MyronCustomCssRepository::CONTEXT_PUBLIC) . "\n" ?>
  <?php if (is_array($currentUser)): ?>
  <link rel="stylesheet" href="<?= myronSiteEscape(myronBuildAssetUrl('runtime/css/style-guide.css')) ?>">
  <script src="<?= myronSiteEscape(myronBuildAssetUrl('runtime/js/app-shell.js')) ?>" defer></script>
  <?php endif; ?>
  <script src="<?= myronSiteEscape(myronBuildAssetUrl('runtime/js/interactive-atoms.min.js')) ?>" defer></script>
  <script src="<?= myronSiteEscape(myronBuildAssetUrl('runtime/js/public-navigation.js')) ?>" defer></script>
  <?php if (myronAnalyticsHeadScript() !== ''): ?>
  <?= myronAnalyticsHeadScript() . "\n" ?>
  <?php endif; ?>
  <?php if (myronAnalyticsEnabled()): ?>
  <script src="<?= myronSiteEscape(myronBuildAssetUrl('runtime/js/analytics-beacon.js')) ?>" defer></script>
  <?php endif; ?>
</head>
<body class="<?= is_array($currentUser) ? 'myron-site-page myron-site-page--authenticated' : 'myron-site-page' ?>">
  <?php if (is_array($currentUser)): ?>
  <?php myronRenderPublicShellHeader($currentUser, ['logoutReturnTo' => $requestUri]); ?>
  <?php endif; ?>
  <div class="myron-site">
    <?= myronPublicNavigationRenderer()->renderContext($headerContext, $basePath, $resolvedPath) . "\n" ?>

    <main class="myron-site__canvas">
      <?php if (is_array($modulePage) && is_callable($modulePage['render'] ?? null)): ?>
      <?= ((string) $modulePage['render']()) . "\n" ?>
      <?php elseif ($page === null): ?>
      <section class="myron-public-empty">
        <h1 class="myron-heading myron-public-empty__title">Published page not found</h1>
        <p class="myron-paragraph myron-paragraph--muted myron-public-empty__text">The requested route does not currently map to a published MyronCMS page.</p>
        <div class="myron-public-empty__actions">
          <a class="myron-button myron-button--intent-neutral myron-button--appearance-outline myron-button--size-md" href="<?= myronSiteEscape($siteActionTarget) ?>"><?= myronSiteEscape($siteActionLabel) ?></a>
        </div>
      </section>
      <?php else: ?>
      <?php myronPublicRenderProfiler()->mark('before_template_render'); ?>
      <?= myronDefinitionTemplateRenderer()->renderPublishedPage($page, $basePath, $footerNavigation) ?>
      <?php myronPublicRenderProfiler()->mark('after_template_render'); ?>
      <?php endif; ?>
    </main>
  </div>
  <?= myronCustomCssRepository()->renderCustomInteractionsScriptTags() . "\n" ?>
  <?php if (myronDefinitionTemplateRenderer()->hadCreativeSections() || $headerCreativeNeedsRuntime || $buttonCreativeNeedsRuntime): ?>
  <script src="<?= myronSiteEscape(myronBuildAssetUrl('runtime/js/creative-runtime.min.js')) ?>" defer></script>
  <?php endif; ?>
</body>
</html>
