<?php

declare(strict_types=1);

function myronDefaultAuthorizedRoute(?array $user = null): string
{
    if (!is_array($user)) {
        return 'auth.login';
    }

    if (
        myronUserCanAccessContent($user)
        || myronUserCanAccessDesign($user)
        || myronUserCanAccessAdministration($user)
    ) {
        return 'dashboard';
    }

    return 'auth.login';
}

/**
 * @return array<string, string>
 */
function myronAppRouteHandlerMap(): array
{
    $root = dirname(__DIR__, 2);

    $handlers = [
        '/api/files' => $root . '/api/routes/files.php',
        '/media/files/stream' => $root . '/site/routes/media-file-stream.php',
        '/media/interactions/stream' => $root . '/site/routes/index.php',
        '/dashboard' => $root . '/admin/routes/dashboard.php',
        '/dashboard/notes/save' => $root . '/admin/routes/dashboard/notes-save.php',
        '/dashboard/notes/delete' => $root . '/admin/routes/dashboard/notes-delete.php',
        '/dashboard/messages/send' => $root . '/admin/routes/dashboard/messages-send.php',
        '/dashboard/messages/read' => $root . '/admin/routes/dashboard/messages-read.php',
        '/dashboard/links/save' => $root . '/admin/routes/dashboard/links-save.php',
        '/dashboard/links/delete' => $root . '/admin/routes/dashboard/links-delete.php',
        '/design/components' => $root . '/admin/routes/design/components.php',
        '/design/components/preview' => $root . '/admin/routes/design/component-preview.php',
        '/design/layout' => $root . '/admin/routes/design/layout.php',
        '/design/navigation' => $root . '/admin/routes/design/navigation.php',
        '/design/footers' => $root . '/admin/routes/design/footers.php',
        '/design/rails' => $root . '/admin/routes/design/rails.php',
        '/design/forms' => $root . '/admin/routes/design/forms.php',
        '/design/primitives' => $root . '/admin/routes/design/primitives.php',
        '/design/custom-css' => $root . '/admin/routes/design/custom-css.php',
        '/design/custom-interactions' => $root . '/admin/routes/design/custom-css.php',
        '/design/tokens' => $root . '/admin/routes/design/tokens.php',
        '/design/token-designer' => $root . '/admin/routes/design/token-designer.php',
        '/design/templates' => $root . '/admin/routes/design/templates.php',
        '/design/template-studio' => $root . '/admin/routes/design/site-type-studio.php',
        '/design/template-studio/site-templates' => $root . '/admin/routes/design/site-type-studio.php',
        '/design/template-studio/page-templates' => $root . '/admin/routes/design/site-type-studio.php',
        '/design/template-studio/document-templates' => $root . '/admin/routes/design/document-templates.php',
        '/design/site-type-studio' => $root . '/admin/routes/design/site-type-studio.php',
        '/design/templates/manager' => $root . '/admin/routes/design/templates-manager.php',
        '/design/templates/preview' => $root . '/admin/routes/design/template-preview.php',
        '/design/sections' => $root . '/admin/routes/design/sections-manager.php',
        '/design/creative-library' => $root . '/admin/routes/design/creative-library.php',
        '/design/section-variants' => $root . '/admin/routes/design/section-variants.php',
        '/design/systems' => $root . '/admin/routes/design/design-systems.php',
        '/design/assets/images' => $root . '/admin/routes/design/assets.php',
        '/design/assets/videos' => $root . '/admin/routes/design/assets.php',
        '/design/assets/audio' => $root . '/admin/routes/design/assets.php',
        '/content/pages' => $root . '/admin/routes/content/pages.php',
        '/content/pages/editor' => $root . '/admin/routes/content/page-editor.php',
        '/content/categories' => $root . '/admin/routes/content/categories.php',
        '/content/comments' => $root . '/admin/routes/content/comments.php',
        '/content/templates' => $root . '/admin/routes/content/templates.php',
        '/content/content-banks' => $root . '/admin/routes/content/content-banks.php',
        '/content/sections' => $root . '/admin/routes/content/sections.php',
        '/content/files' => $root . '/admin/routes/content/files.php',
        '/content/files/stream' => $root . '/admin/routes/content/file.php',
        '/content/assets/images' => $root . '/admin/routes/content/asset-manager.php',
        '/content/assets/videos' => $root . '/admin/routes/content/asset-manager.php',
        '/content/assets/audio' => $root . '/admin/routes/content/asset-manager.php',
        '/content/assets/documents' => $root . '/admin/routes/content/asset-manager.php',
        '/content/menus' => $root . '/admin/routes/content/menu-manager.php',
        '/administration/menus' => $root . '/admin/routes/content/menu-manager.php',
        '/administration/site-setup' => $root . '/admin/routes/administration/site-setup.php',
        '/administration/site-settings' => $root . '/admin/routes/administration/site-settings.php',
        '/administration/form-protection' => $root . '/admin/routes/administration/form-protection.php',
        '/admin/analytics' => $root . '/admin/routes/analytics/index.php',
        '/analytics' => $root . '/admin/routes/analytics/index.php',
        '/administration/analytics' => $root . '/admin/routes/analytics/index.php',
        '/administration/snapshot' => $root . '/admin/routes/administration/snapshot.php',
        '/administration/license' => $root . '/admin/routes/administration/license.php',
        '/administration/license-manager' => $root . '/admin/routes/administration/license-manager.php',
        '/administration/mail' => $root . '/admin/routes/administration/mail-setup.php',
        '/administration/notification-emails' => $root . '/admin/routes/administration/notification-emails.php',
        '/administration/changelog' => $root . '/admin/routes/administration/changelog.php',
        '/administration/ai-connections' => $root . '/admin/routes/administration/ai-connections.php',
        '/administration/audit-log' => $root . '/admin/routes/administration/audit-log.php',
        '/administration/roles-users' => $root . '/admin/routes/administration/roles-users.php',
        '/identity/users' => $root . '/admin/routes/identity/users.php',
        '/identity/profile' => $root . '/admin/routes/identity/profile.php',
        '/auth/login' => $root . '/auth/routes/login.php',
        '/auth/logout' => $root . '/auth/routes/logout.php',
        '/auth/register' => $root . '/auth/routes/register.php',
        '/auth/password-reset' => $root . '/auth/routes/password-reset.php',
        '/extensions/register' => $root . '/admin/routes/extensions/register.php',
        '/extensions/marketplace' => $root . '/admin/routes/extensions/marketplace.php',
        '/extensions' => $root . '/admin/routes/extensions/installed.php',
    ];

    return array_merge($handlers, myronModuleRegistry()->adminRoutes(), myronExtensionLoader()->getAdminRoutes());
}

/**
 * @return array<string, string>
 */
function myronAppRouteCapabilityMap(): array
{
    $capabilities = [
        '/admin/analytics' => 'analytics.native',
        '/analytics' => 'analytics.native',
        '/administration/analytics' => 'analytics.native',
        '/administration/audit-log' => 'audit.admin_surface',
        '/administration/snapshot' => 'snapshots.basic',
        '/administration/ai-connections' => 'mcp.site_operations',
        '/design/template-studio/document-templates' => 'templates.document',
        '/design/section-variants' => 'templates.section_variants',
        '/extensions/register' => 'extensions.local_registration',
        '/extensions/marketplace' => 'extensions.marketplace_install',
        '/extensions' => 'extensions.marketplace_install',
    ];

    return array_replace($capabilities, myronModuleRegistry()->adminRouteCapabilities());
}

function myronAppRouteRequiredCapability(string $requestPath): string
{
    $map = myronAppRouteCapabilityMap();
    return (string) ($map[$requestPath] ?? '');
}

function myronAppRouteAllowsCurrentLicense(string $capability): bool
{
    $capability = trim($capability);
    if ($capability === '' || !function_exists('myronEntitlementGate')) {
        return true;
    }
    try {
        $decision = myronEntitlementGate()->evaluate($capability);
    } catch (Throwable) {
        return false;
    }

    return in_array((string) ($decision['outcome'] ?? ''), ['allowed', 'warn'], true);
}

function myronRenderAdminEntitlementDenied(string $capability): void
{
    http_response_code(403);
    header('Content-Type: text/html; charset=UTF-8');
    $policy = function_exists('myronEntitlementPresentationPolicy') ? myronEntitlementPresentationPolicy() : null;
    $decision = $policy instanceof MyronEntitlementPresentationPolicy
        ? $policy->decisionForCapability($capability)
        : [
            'remediationLabel' => 'Open License',
            'remediationRoute' => 'administration.license',
            'remediationQuery' => [],
        ];
    $remediationHref = myronBuildAdminUrl(
        (string) ($decision['remediationRoute'] ?? 'administration.license'),
        is_array($decision['remediationQuery'] ?? null) ? $decision['remediationQuery'] : []
    );
    $remediationLabel = (string) ($decision['remediationLabel'] ?? 'Open License');
    $subtitle = MyronEntitlementPresentationPolicy::isModuleCapability($capability)
        ? 'This Module feature is not active on this site. Open Modules to redeem a license or review installed status.'
        : 'This feature is not available for the current license. Review your license or choose an available workspace action.';

    echo '<!DOCTYPE html><html lang="' . myronEscape(myronSiteLanguage()) . '"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>' . myronEscape(myronComposeDocumentTitle('Feature Unavailable')) . '</title>' . myronRenderSiteFaviconLink() . myronRenderDefinitionFontHeadTags() . '<link rel="stylesheet" href="' . myronEscape(myronBuildAssetUrl('runtime/css/tokens.css')) . '"><link rel="stylesheet" href="' . myronEscape(myronBuildAssetUrl('runtime/css/runtime-fonts.css')) . '"><link rel="stylesheet" href="' . myronEscape(myronBuildAssetUrl('runtime/css/runtime-token-overrides.css')) . '"><link rel="stylesheet" href="' . myronEscape(myronBuildAssetUrl('runtime/css/base.css')) . '"><link rel="stylesheet" href="' . myronEscape(myronBuildAssetUrl('runtime/css/components.css')) . '"><link rel="stylesheet" href="' . myronEscape(myronBuildAssetUrl('runtime/css/style-guide.css')) . '"></head><body><main class="mc-page-canvas mc-page-canvas--site mc-auth-layout"><section class="myron-auth-form myron-auth-form--standard"><div class="mc-workspace__header mc-workspace__header--auth"><span class="mc-workspace__eyebrow">License</span><div class="mc-workspace__title-row"><h1 class="mc-workspace__title">Feature Unavailable</h1></div><p class="mc-workspace__subtitle">' . myronEscape($subtitle) . '</p></div><div class="sg-card__actions"><a class="sg-button sg-button--primary" href="' . myronEscape($remediationHref) . '">' . myronEscape($remediationLabel) . '</a><a class="sg-button sg-button--secondary" href="' . myronEscape(myronBuildAdminUrl(myronDefaultAuthorizedRoute(myronCurrentUser()))) . '">Return to Workspace</a></div></section></main></body></html>';
}

function myronDispatchAppRequest(): void
{
    $requestUri = (string) ($_SERVER['REQUEST_URI'] ?? '/');
    $requestPath = myronResolveAppRequestPath($requestUri);
    $rawRequestPath = myronResolveAppRequestPathPreservingTrailingSlash($requestUri);

    if ($requestPath === '/') {
        myronRedirect(myronBuildAdminUrl(myronDefaultAuthorizedRoute(myronCurrentUser())));
    }

    $legacyKey = ltrim($requestPath, '/');
    $legacyAliases = myronLegacyAppRouteAliases();
    if (isset($legacyAliases[$legacyKey])) {
        myronRedirect(myronBuildAdminUrl($legacyAliases[$legacyKey], $_GET));
    }

    // APO-186 — /api/v1/... requests dispatch through the action substrate.
    if ($requestPath === '/api/v1/public-interactions/token') {
        require dirname(__DIR__, 2) . '/api/routes/public-interaction-token.php';
        return;
    }
    if (preg_match('#^/api/v1/content/forms/[^/]+/submissions$#', $requestPath) === 1 && strtoupper((string) ($_SERVER['REQUEST_METHOD'] ?? 'GET')) === 'POST') {
        require dirname(__DIR__, 2) . '/api/routes/form-submission.php';
        return;
    }
    if (preg_match('#^/api/v1/content/quizzes/[^/]+/attempts$#', $requestPath) === 1) {
        require dirname(__DIR__, 2) . '/api/routes/quiz-attempt-submission.php';
        return;
    }
    if (
        (
            $requestPath === '/api/v1/content/blog-comments'
            || preg_match('#^/api/v1/content/pages/[^/]+/comments$#', $requestPath) === 1
        )
        && strtoupper((string) ($_SERVER['REQUEST_METHOD'] ?? 'GET')) === 'POST'
    ) {
        require dirname(__DIR__, 2) . '/api/routes/blog-comment.php';
        return;
    }
    if (str_starts_with($requestPath, '/api/v1/')) {
        require dirname(__DIR__, 2) . '/api/routes/api-v1.php';
        return;
    }

    if ($requestPath === '/verify-notification-email') {
        require dirname(__DIR__, 2) . '/api/routes/notification-email-verify.php';
        return;
    }

    if (
        ($requestPath === '/.well-known/oauth-authorization-server' && $rawRequestPath === '/.well-known/oauth-authorization-server')
        || str_starts_with($requestPath, '/.well-known/oauth-protected-resource')
    ) {
        require dirname(__DIR__, 2) . '/api/routes/mcp-oauth-metadata.php';
        return;
    }
    if ($requestPath === '/.well-known/mcp' && $rawRequestPath === '/.well-known/mcp') {
        require dirname(__DIR__, 2) . '/api/routes/mcp-well-known.php';
        return;
    }
    if ($requestPath === '/.well-known' || str_starts_with($requestPath, '/.well-known/')) {
        http_response_code(404);
        header('Content-Type: application/json; charset=utf-8');
        header('X-Content-Type-Options: nosniff');
        echo json_encode(['error' => 'well_known_not_found'], JSON_UNESCAPED_SLASHES);
        return;
    }
    if ($requestPath === '/oauth/register') {
        require dirname(__DIR__, 2) . '/api/routes/mcp-oauth-register.php';
        return;
    }
    if ($requestPath === '/oauth/authorize') {
        require dirname(__DIR__, 2) . '/api/routes/mcp-oauth-authorize.php';
        return;
    }
    if ($requestPath === '/oauth/token') {
        require dirname(__DIR__, 2) . '/api/routes/mcp-oauth-token.php';
        return;
    }

    // APO-198 — MCP Streamable HTTP transport.
    // Canonical path: /mcp (operator-facing). Protocol version is negotiated
    // via the initialize handshake, not the URL. The legacy /api/mcp/v1/*
    // path is preserved as a soft-deprecated alias so clients configured
    // during the original arc keep working through a transition.
    if ($requestPath === '/mcp' || str_starts_with($requestPath, '/mcp/')) {
        require dirname(__DIR__, 2) . '/api/routes/mcp-v1.php';
        return;
    }
    if (str_starts_with($requestPath, '/api/mcp/v1/')) {
        require dirname(__DIR__, 2) . '/api/routes/mcp-v1.php';
        return;
    }

    $routeHandlers = myronAppRouteHandlerMap();
    if (isset($routeHandlers[$requestPath])) {
        $requiredCapability = myronAppRouteRequiredCapability($requestPath);
        if ($requiredCapability !== '' && myronCurrentUser() !== null && !myronAppRouteAllowsCurrentLicense($requiredCapability)) {
            myronRenderAdminEntitlementDenied($requiredCapability);
            return;
        }
        require $routeHandlers[$requestPath];
        return;
    }

    if (str_starts_with($requestPath, '/design/site-type-studio/')) {
        require $routeHandlers['/design/site-type-studio'];
        return;
    }

    if (str_starts_with($requestPath, '/design/template-studio/')) {
        $requiredCapability = myronAppRouteRequiredCapability('/design/template-studio/document-templates');
        if (str_starts_with($requestPath, '/design/template-studio/document-templates') && myronCurrentUser() !== null && !myronAppRouteAllowsCurrentLicense($requiredCapability)) {
            myronRenderAdminEntitlementDenied($requiredCapability);
            return;
        }
        require $routeHandlers['/design/template-studio'];
        return;
    }

    http_response_code(404);
    header('Content-Type: text/html; charset=UTF-8');
    echo '<!DOCTYPE html><html lang="' . myronEscape(myronSiteLanguage()) . '"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>' . myronEscape(myronComposeDocumentTitle('Not Found')) . '</title>' . myronRenderSiteFaviconLink() . myronRenderDefinitionFontHeadTags() . '<link rel="stylesheet" href="' . myronEscape(myronBuildAssetUrl('runtime/css/tokens.css')) . '"><link rel="stylesheet" href="' . myronEscape(myronBuildAssetUrl('runtime/css/runtime-fonts.css')) . '"><link rel="stylesheet" href="' . myronEscape(myronBuildAssetUrl('runtime/css/runtime-token-overrides.css')) . '"><link rel="stylesheet" href="' . myronEscape(myronBuildAssetUrl('runtime/css/base.css')) . '"><link rel="stylesheet" href="' . myronEscape(myronBuildAssetUrl('runtime/css/components.css')) . '"><link rel="stylesheet" href="' . myronEscape(myronBuildAssetUrl('runtime/css/style-guide.css')) . '"></head><body><main class="mc-page-canvas mc-page-canvas--site mc-auth-layout"><section class="myron-auth-form myron-auth-form--standard"><div class="mc-workspace__header mc-workspace__header--auth"><span class="mc-workspace__eyebrow">Application Route</span><div class="mc-workspace__title-row"><h1 class="mc-workspace__title">Not Found</h1></div><p class="mc-workspace__subtitle">The requested MyronCMS route could not be resolved.</p></div></section></main></body></html>';
}

function myronResolveAppRequestPathPreservingTrailingSlash(string $requestUri): string
{
    $requestPath = parse_url($requestUri, PHP_URL_PATH);
    $resolvedPath = is_string($requestPath) ? $requestPath : '/';
    $basePath = myronAdminBasePath();

    if ($basePath !== '' && ($resolvedPath === $basePath || str_starts_with($resolvedPath, $basePath . '/'))) {
        $resolvedPath = substr($resolvedPath, strlen($basePath)) ?: '/';
    }

    $resolvedPath = '/' . ltrim($resolvedPath, '/');
    $resolvedPath = preg_replace('#/+#', '/', $resolvedPath) ?: '/';

    return $resolvedPath === '/index.php' ? '/' : $resolvedPath;
}
