<?php

declare(strict_types=1);

if (!defined('APP_ROOT')) {
    define('APP_ROOT', dirname(__DIR__));
}

function app_env(string $name, ?string $default = null): ?string
{
    $value = getenv($name);
    if ($value === false || $value === '') {
        return $default;
    }

    return $value;
}

function app_is_dev(): bool
{
    return app_env('APP_ENV', 'prod') === 'dev';
}

function app_is_https(): bool
{
    return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
        || (($_SERVER['SERVER_PORT'] ?? null) === '443');
}

function app_start_session(): void
{
    if (PHP_SAPI === 'cli' || session_status() === PHP_SESSION_ACTIVE) {
        return;
    }

    $sessionPath = app_env('APP_SESSION_PATH', APP_ROOT . '/var/sessions');
    if ($sessionPath !== null && !is_dir($sessionPath)) {
        @mkdir($sessionPath, 0700, true);
    }

    if ($sessionPath !== null && is_dir($sessionPath) && is_writable($sessionPath)) {
        session_save_path($sessionPath);
    }

    session_set_cookie_params([
        'lifetime' => 0,
        'path' => '/',
        'domain' => '',
        'secure' => app_is_https(),
        'httponly' => true,
        'samesite' => 'Lax',
    ]);

    session_name(app_env('APP_SESSION_NAME', 'kaffeeliste_session') ?? 'kaffeeliste_session');
    session_start();
}

function app_csrf_token(): string
{
    app_start_session();

    if (!isset($_SESSION) || !is_array($_SESSION)) {
        $_SESSION = [];
    }

    if (empty($_SESSION['csrf_token']) || !is_string($_SESSION['csrf_token'])) {
        $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
    }

    return $_SESSION['csrf_token'];
}

function app_csrf_field(): string
{
    return '<input type="hidden" name="csrf_token" value="'
        . htmlspecialchars(app_csrf_token(), ENT_QUOTES, 'UTF-8')
        . '">';
}

function app_verify_csrf(?string $token): bool
{
    app_start_session();

    if (!isset($_SESSION) || !is_array($_SESSION)) {
        $_SESSION = [];
    }

    return is_string($token)
        && isset($_SESSION['csrf_token'])
        && is_string($_SESSION['csrf_token'])
        && hash_equals($_SESSION['csrf_token'], $token);
}

function app_require_csrf(): void
{
    if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
        return;
    }

    if (!app_verify_csrf($_POST['csrf_token'] ?? null)) {
        http_response_code(419);
        die('CSRF validation failed.');
    }
}
