<?php

require __DIR__ . '/src/bootstrap.php';

use WPD\Application\Config;
use WPD\Security\AccessGuard;
use WPD\Security\ActivationStore;
use WPD\Security\AttemptLimiter;
use WPD\Security\SystemClock;
use WPD\Security\TransportPolicy;
use WPD\Web\Controller;
use WPD\Web\View;

header('X-Content-Type-Options: nosniff');
header('X-Frame-Options: DENY');
header('X-Robots-Tag: noindex, nofollow, noarchive');
header('Referrer-Policy: no-referrer');
header("Content-Security-Policy: default-src 'self'; img-src 'self' data:; style-src 'self'; script-src 'self'; form-action 'self'; frame-ancestors 'none'; base-uri 'none'");
header('Cache-Control: no-store, private');

$method = isset($_SERVER['REQUEST_METHOD']) ? strtoupper((string) $_SERVER['REQUEST_METHOD']) : 'GET';
if (!in_array($method, array('GET', 'HEAD', 'POST'), true)) {
    http_response_code(405);
    header('Allow: GET, HEAD, POST');
    (new View())->restricted();
    exit;
}

$config = Config::load(__DIR__);
if (!$config->isValid()) {
    (new View())->sealed($config->error());
    exit;
}

$transport = new TransportPolicy($config, $_SERVER);
if ($transport->mode() === TransportPolicy::BLOCKED_HTTP) {
    http_response_code(403);
    (new View())->insecureHttp();
    exit;
}
if (!$transport->clientAllowed()) {
    http_response_code(404);
    (new View())->restricted();
    exit;
}

$secure = $transport->mode() === TransportPolicy::HTTPS;
session_name($secure ? '__Host-wpd_session' : 'wpd_emergency_session');
session_set_cookie_params(array(
    'lifetime' => 0,
    'path' => '/',
    'secure' => $secure,
    'httponly' => true,
    'samesite' => 'Strict',
));
ini_set('session.use_strict_mode', '1');
session_start();

$clock = new SystemClock();
$activation = new ActivationStore($config, $clock, __DIR__ . '/var');
$limiter = new AttemptLimiter($config, $clock, __DIR__ . '/var');
$guard = new AccessGuard($config, $activation, $limiter, $clock, $transport->mode(), $transport->clientAddress());
$controller = new Controller($config, $transport, $guard);
$controller->handle();
