<?php
declare(strict_types=1);

function csrf_token(): string
{
    if (empty($_SESSION['_csrf'])) {
        $_SESSION['_csrf'] = bin2hex(random_bytes(32));
    }
    return $_SESSION['_csrf'];
}

function csrf_field(): string
{
    return '<input type="hidden" name="_csrf" value="' . e(csrf_token()) . '">';
}

function verify_csrf(): void
{
    $token = (string) ($_POST['_csrf'] ?? $_SERVER['HTTP_X_CSRF_TOKEN'] ?? '');
    if ($token === '' || !hash_equals(csrf_token(), $token)) {
        http_response_code(419);
        exit('Oturum doğrulaması başarısız. Sayfayı yenileyip tekrar deneyin.');
    }
}

function app_encrypt(string $plain): string
{
    if ($plain === '') return '';
    $key = hash('sha256', (string) app_config('app.key'), true);
    $iv = random_bytes(12);
    $tag = '';
    $cipher = openssl_encrypt($plain, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $iv, $tag);
    if ($cipher === false) return '';
    return 'enc:' . base64_encode($iv . $tag . $cipher);
}

function app_decrypt(?string $payload): string
{
    if (!$payload) return '';
    if (!str_starts_with($payload, 'enc:')) return $payload;
    $raw = base64_decode(substr($payload, 4), true);
    if ($raw === false || strlen($raw) < 29) return '';
    $iv = substr($raw, 0, 12);
    $tag = substr($raw, 12, 16);
    $cipher = substr($raw, 28);
    $key = hash('sha256', (string) app_config('app.key'), true);
    $plain = openssl_decrypt($cipher, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $iv, $tag);
    return $plain === false ? '' : $plain;
}

function client_ip(): string
{
    $candidates = [
        $_SERVER['HTTP_CF_CONNECTING_IP'] ?? '',
        $_SERVER['HTTP_X_FORWARDED_FOR'] ?? '',
        $_SERVER['REMOTE_ADDR'] ?? '',
    ];
    foreach ($candidates as $candidate) {
        $ip = trim(explode(',', $candidate)[0]);
        if (filter_var($ip, FILTER_VALIDATE_IP)) return $ip;
    }
    return '0.0.0.0';
}

function rate_limit_bucket(string $key, int $seconds): array
{
    $_SESSION['_rate'] ??= [];
    $now = time();
    $bucket = array_values(array_filter(
        $_SESSION['_rate'][$key] ?? [],
        static fn($timestamp): bool => (int) $timestamp > $now - $seconds
    ));
    $_SESSION['_rate'][$key] = $bucket;
    return $bucket;
}

function rate_limit_allowed(string $key, int $max, int $seconds): bool
{
    return count(rate_limit_bucket($key, $seconds)) < $max;
}

function rate_limit_hit(string $key, int $seconds): void
{
    $bucket = rate_limit_bucket($key, $seconds);
    $bucket[] = time();
    $_SESSION['_rate'][$key] = $bucket;
}

function rate_limit_clear(string $key): void
{
    unset($_SESSION['_rate'][$key]);
}

function rate_limit(string $key, int $max, int $seconds): bool
{
    if (!rate_limit_allowed($key, $max, $seconds)) return false;
    rate_limit_hit($key, $seconds);
    return true;
}
