<?php
declare(strict_types=1);

/**
 * CSRF 発行・検証ユーティリティ
 * - hidden フィールド名は "_csrf"（LD-01 要件）
 * - フォーム側は <?= csrf_input_tag() ?> を差し込むだけでOK
 *
 * 依存: helpers.php（→ config.php でセッション開始済み）
 */

require_once __DIR__ . '/../helpers.php';

if (!function_exists('csrf_get_token')) {
    /**
     * セッション内の CSRF トークンを取得（なければ生成）
     */
    function csrf_get_token(): string {
        $key = '_csrf_token';
        if (empty($_SESSION[$key]) || !is_string($_SESSION[$key])) {
            // 32byte のランダム値を base64 で保存
            $_SESSION[$key] = rtrim(strtr(base64_encode(random_bytes(32)), '+/', '-_'), '=');
        }
        return $_SESSION[$key];
    }
}

if (!function_exists('csrf_input_tag')) {
    /**
     * フォーム用 hidden タグを返す
     * 例）<form ...><?= csrf_input_tag() ?></form>
     */
    function csrf_input_tag(): string {
        return '<input type="hidden" name="_csrf" value="' . h(csrf_get_token()) . '">';
    }
}

if (!function_exists('csrf_check_or_die')) {
    /**
     * POST受信時にCSRF検証を行い、失敗時は 400 を返して終了
     * - 非POSTやCLI実行時は何もしない
     */
    function csrf_check_or_die(): void {
        if (PHP_SAPI === 'cli') return;

        $method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
        if (strtoupper((string)$method) !== 'POST') return;

        $posted = $_POST['_csrf'] ?? '';
        $sess   = $_SESSION['_csrf_token'] ?? '';

        $ok = is_string($posted) && is_string($sess) && $posted !== '' && hash_equals($sess, $posted);
        if (!$ok) {
            http_response_code(400);
            header('Content-Type: text/plain; charset=UTF-8');
            exit('Bad Request: invalid CSRF token');
        }
    }
}
