<?php
session_cache_limiter('');
header('Cache-Control: public, max-age=600');

require __DIR__ . '/../vendor/autoload.php';
// Tambahkan header keamanan dasar (fallback via PHP)
$__isHttps = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || (($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? '') === 'https');

// Cache headers untuk static assets
$__uri = $_SERVER['REQUEST_URI'] ?? '/';
if (preg_match('/\.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$/i', $__uri)) {
    header("Cache-Control: public, max-age=31536000, immutable");
    header("Expires: " . gmdate('D, d M Y H:i:s', time() + 31536000) . ' GMT');
}
header("X-Content-Type-Options: nosniff");
//header("X-Frame-Options: SAMEORIGIN");
//header("Referrer-Policy: strict-origin-when-cross-origin");
//header("Cross-Origin-Opener-Policy: same-origin");
// CSP yang mengizinkan resource eksternal yang diperlukan tema
//header("Content-Security-Policy: default-src 'self'; img-src 'self' data: https: *.herringbucket.com *.com *.bing.net *.mm.bing.net  img.youtube.com; script-src 'self' 'unsafe-inline' 'unsafe-eval' code.jquery.com cdnjs.cloudflare.com herringbucket.com wayfarerorthodox.com professionaltrafficmonitor.com cdn.tailwindcss.com *.accuknox.com effectuallyconceptcontinuous.com; style-src 'self' 'unsafe-inline' cdnjs.cloudflare.com; connect-src 'self'; frame-src 'self' www.youtube.com youtube.com; frame-ancestors 'self'; upgrade-insecure-requests; block-all-mixed-content");
 //header("Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' code.jquery.com cdnjs.cloudflare.com cdn.tailwindcss.com; script-src-elem 'self' 'unsafe-inline' code.jquery.com cdnjs.cloudflare.com cdn.tailwindcss.com; connect-src 'self'; img-src 'self' data: https:; style-src 'self' 'unsafe-inline' fonts.googleapis.com; font-src 'self' fonts.gstatic.com; object-src 'none'; base-uri 'self'; frame-ancestors 'none'; upgrade-insecure-requests");

if ($__isHttps) {
    header("Strict-Transport-Security: max-age=31536000; includeSubDomains; preload");
}
// Bootstrap Eloquent if available
if (class_exists(\Illuminate\Database\Capsule\Manager::class)) {
    require __DIR__ . '/../app/bootstrap_eloquent.php';
}

$site = require __DIR__ . '/../config/site.php';
$routes = require __DIR__ . '/../config/routes.php';

$method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
$uri = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH) ?? '/';
$uri = $uri === '' ? '/' : $uri;

// Page Output Cache (preflight)
$__cache_enabled = !empty($site['use_cache']);
$__cache_ttl = (int)($site['page_cache_ttl'] ?? 300);
$__request_method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
$__request_uri = $_SERVER['REQUEST_URI'] ?? '/';
$__cache_file = null;
if ($__cache_enabled && $__request_method === 'GET') {
    $pathRaw = parse_url($__request_uri, PHP_URL_PATH) ?? '/';
    // Skip admin area caching (support subfolder base_url)
    $adminPrefix = (($site['base_url'] ?? '') !== '' ? '/' . trim($site['base_url'], '/') : '') . '/admin';
    $isAdminReq = (strpos($pathRaw, '/admin') === 0) || (strpos($pathRaw, $adminPrefix) === 0);
    if (!$isAdminReq) {
        $cacheDir = __DIR__ . '/../storage/cache/pages';
        if (!is_dir($cacheDir)) {
            @mkdir($cacheDir, 0777, true);
        }
        $host = $_SERVER['HTTP_HOST'] ?? 'localhost';
        $query = parse_url($__request_uri, PHP_URL_QUERY) ?? '';
        $key = sha1($host . '|' . $pathRaw . '|' . $query);
        $__cache_file = $cacheDir . '/' . $key . '.html';
        if (is_file($__cache_file) && (time() - filemtime($__cache_file)) < $__cache_ttl) {
            header('X-Cache: HIT');
            readfile($__cache_file);
            exit;
        }
    }
}

// Normalisasi base path jika aplikasi berjalan di subfolder (mis. /cms)
$docRoot = isset($_SERVER['DOCUMENT_ROOT']) ? str_replace('\\', '/', $_SERVER['DOCUMENT_ROOT']) : '';
$scriptFilename = isset($_SERVER['SCRIPT_FILENAME']) ? str_replace('\\', '/', $_SERVER['SCRIPT_FILENAME']) : '';
$scriptRel = '';
if ($docRoot !== '' && $scriptFilename !== '' && strpos($scriptFilename, $docRoot) === 0) {
    $scriptRel = substr($scriptFilename, strlen($docRoot)); // contoh: /cms/public/index.php
}
// Ambil base app: direktori induk dari tempat index.php berada, hilangkan /public di akhir jika ada
$appBase = rtrim(preg_replace('#/public$#', '', dirname($scriptRel)), '/'); // contoh: /cms
if ($appBase && $appBase !== '/' && strpos($uri, $appBase) === 0) {
    $uri = substr($uri, strlen($appBase));
}

// Tambahan: hormati base_url dari konfigurasi site.php secara eksplisit
$cfgBase = isset($site['base_url']) && $site['base_url'] !== '' ? '/' . trim($site['base_url'], '/') : '';
if ($cfgBase !== '' && strpos($uri, $cfgBase) === 0) {
    $uri = substr($uri, strlen($cfgBase));
}

$uri = rtrim($uri, '/') ?: '/';

// Khusus untuk sitemap.xml, arahkan ke route yang benar
if ($uri === '/sitemap.xml') {
    $uri = '/sitemap.xml';
}

function matchRoute(string $method, string $path, array $routes): array
{
    foreach ($routes as $r) {
        [$m, $pattern, $handler] = $r;
        if (strtoupper($m) !== strtoupper($method)) {
            continue;
        }
        if ($pattern === '/') {
            $regex = '#^/$#';
        } else {
            $regex = preg_replace('#\{(\w+)\}#', '(?P<$1>[^/]+)', $pattern);
            $regex = '#^' . $regex . '$#';
        }
        if (preg_match($regex, $path, $matches)) {
            $params = [];
            foreach ($matches as $k => $v) {
                if (!is_int($k)) {
                    $params[$k] = $v;
                }
            }
            return [$handler, $params];
        }
    }
    return [null, []];
}

[$handler, $params] = matchRoute($method, $uri, $routes);

if (!$handler) {
    http_response_code(404);
    $recentLimit = (int)($site['getRecentPosts_limit'] ?? 20);
    $recent = getRecentPosts($recentLimit);
    view('404', ['recent' => $recent]);
    exit;
}

[$controllerName, $methodName] = explode('@', $handler, 2);
$controllerClass = 'App\\Controllers\\' . $controllerName;

if (!class_exists($controllerClass)) {
    http_response_code(500);
    echo 'Controller ' . $controllerClass . ' not found';
    exit;
}

$controller = new $controllerClass();
if (!method_exists($controller, $methodName)) {
    http_response_code(500);
    echo 'Method ' . $methodName . ' not found';
    exit;
}

// Begin output buffering so we can store page cache after rendering
if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false && function_exists('ob_gzhandler')) {
    ob_start('ob_gzhandler');
} else {
    ob_start();
}

$ref = new \ReflectionMethod($controller, $methodName);
if ($ref->getNumberOfParameters() === 0) {
    $controller->$methodName();
} else {
    $controller->$methodName($params);
}

// Store to page cache if enabled and target file is set
$__output = ob_get_contents();
if ($__cache_file && $__output !== false && $__output !== '') {
    @file_put_contents($__cache_file, $__output);
    header('X-Cache: MISS');
}
ob_end_flush();
