<?php
// Shared application colour-mode bootstrap. Keep this script before page styles so
// the saved mode is applied before the first paint (avoids a light-theme flash).
$assetsUrl = $assetsUrl ?? '';
?>
<script>
    (function () {
        var key = 'ppphp-color-theme';
        var choice = 'system';
        var allowed = ['system', 'light', 'midnight', 'dracula', 'gruvbox', 'rosepine'];
        try {
            var saved = window.localStorage.getItem(key);
            if (saved === 'dark') saved = 'midnight';
            if (saved === 'graphite') saved = 'dracula';
            if (saved === 'aurora') saved = 'gruvbox';
            if (allowed.indexOf(saved) !== -1) choice = saved;
        } catch (error) {}
        var systemDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
        var theme = choice === 'system' ? (systemDark ? 'dark' : 'light') : (choice === 'light' ? 'light' : 'dark');
        document.documentElement.setAttribute('data-pp-theme-choice', choice);
        document.documentElement.setAttribute('data-pp-theme', theme);
        document.documentElement.setAttribute('data-bs-theme', theme);
        document.documentElement.style.colorScheme = theme;
    }());
</script>
<?php
// ── CSRF token + auto-attach ────────────────────────────────────────────────
// Expose the session CSRF token to the page and transparently attach it to every
// same-origin unsafe request (fetch / XHR / form POST). This lets controllers
// enforce Security::CSRF()->CheckRequest() without touching each form or fetch.
// Purely additive: it only ADDS a header/field; nothing depends on it until a
// controller opts into the check.
if (session_status() === PHP_SESSION_ACTIVE):
    $__csrf = '';
    try { $__csrf = \PpPhp\Core\Security::CSRF()->Token(); } catch (\Throwable $e) { $__csrf = ''; }
    if ($__csrf !== ''):
?>
<meta name="csrf-token" content="<?= htmlspecialchars($__csrf, ENT_QUOTES) ?>">
<script>
(function () {
    var m = document.querySelector('meta[name="csrf-token"]');
    var token = m ? m.getAttribute('content') : '';
    if (!token) return;
    var unsafe = /^(POST|PUT|PATCH|DELETE)$/i;
    function sameOrigin(url) {
        try { return new URL(url, location.href).origin === location.origin; }
        catch (e) { return true; } // relative URL → same origin
    }
    // 1) fetch — merge the header in for same-origin unsafe requests only.
    if (window.fetch) {
        var _fetch = window.fetch;
        window.fetch = function (input, init) {
            init = init || {};
            var isReq = (typeof input === 'object' && input && 'url' in input);
            var url = (typeof input === 'string') ? input : (isReq ? input.url : '');
            var method = init.method || (isReq ? input.method : 'GET') || 'GET';
            if (unsafe.test(method) && sameOrigin(url)) {
                var h = new Headers(init.headers || (isReq ? input.headers : {}) || {});
                if (!h.has('X-CSRF-Token')) h.set('X-CSRF-Token', token);
                init.headers = h;
            }
            return _fetch.call(this, input, init);
        };
    }
    // 2) XMLHttpRequest — same treatment.
    var _open = XMLHttpRequest.prototype.open;
    var _send = XMLHttpRequest.prototype.send;
    XMLHttpRequest.prototype.open = function (method, url) {
        this.__ppM = method; this.__ppU = url;
        return _open.apply(this, arguments);
    };
    XMLHttpRequest.prototype.send = function () {
        try {
            if (unsafe.test(this.__ppM || '') && sameOrigin(this.__ppU || '')) {
                this.setRequestHeader('X-CSRF-Token', token);
            }
        } catch (e) {}
        return _send.apply(this, arguments);
    };
    // 3) navigator.sendBeacon — pagehide autosaves can't set a header, so route
    //    same-origin beacons through the (wrapped) keepalive fetch instead: it
    //    survives page unload just like a beacon AND picks up the X-CSRF-Token
    //    from the fetch wrapper above. Cross-origin beacons keep the native path.
    if (navigator.sendBeacon) {
        var _beacon = navigator.sendBeacon.bind(navigator);
        navigator.sendBeacon = function (url, data) {
            try {
                if (sameOrigin(url)) {
                    window.fetch(url, { method: 'POST', credentials: 'same-origin', keepalive: true, body: data });
                    return true;
                }
            } catch (e) {}
            return _beacon(url, data);
        };
    }
    // 4) classic form POSTs — inject a hidden _token if the form lacks one.
    document.addEventListener('submit', function (e) {
        var f = e.target;
        if (!f || f.tagName !== 'FORM' || (f.method || 'get').toLowerCase() !== 'post') return;
        var action = f.getAttribute('action');
        if (action && !sameOrigin(action)) return;
        if (f.querySelector('input[name="_token"], input[name="csrf_token"]')) return;
        var i = document.createElement('input');
        i.type = 'hidden'; i.name = '_token'; i.value = token;
        f.appendChild(i);
    }, true);
}());
</script>
<?php endif; endif; ?>
<?php
// Cache-bust the theme assets by file mtime so an edit to app-theme.css / .js is
// picked up on the next load instead of being served stale from the browser cache
// (these are long-lived static files with no version in their path otherwise).
$__assetFsBase = null;
foreach ([constant('BASE_PATH') . '/public/assets', constant('BASE_PATH') . '/assets'] as $__cand) {
    if (is_dir($__cand)) { $__assetFsBase = $__cand; break; }
}
$__ver = static function (string $rel) use ($__assetFsBase): string {
    if ($__assetFsBase && is_file($__assetFsBase . '/' . $rel)) {
        return '?v=' . (string) (@filemtime($__assetFsBase . '/' . $rel) ?: '');
    }
    return '';
};
?>
<link href="<?= htmlspecialchars((string)$assetsUrl) ?>/css/app-theme.css<?= $__ver('css/app-theme.css') ?>" rel="stylesheet">
<script src="<?= htmlspecialchars((string)$assetsUrl) ?>/js/app-theme.js<?= $__ver('js/app-theme.js') ?>" defer></script>
<?php
// Visitor-analytics beacon. Sends the device/engagement detail only the browser
// knows (timezone, screen, connection, active time) to /pp/visit so the Visitors
// console shows accurate data. Guarded so client bundles — which carry no
// analytics code — skip it entirely. Loads once, deferred, never blocking.
if (class_exists(\PpPhp\Core\Analytics\VisitorLog::class)):
    $ppVisitUrl = preg_replace('#/assets/?$#', '', (string) ($assetsUrl ?? '')) . '/pp/visit';
?>
<script>window.__PP_VISIT=<?= json_encode($ppVisitUrl, JSON_UNESCAPED_SLASHES) ?>;</script>
<script src="<?= htmlspecialchars((string) ($assetsUrl ?? '')) ?>/js/pp-visit.js" defer></script>
<?php endif; ?>
