<?php
declare(strict_types=1);

require_once __DIR__ . '/config.php';

function golder_ensure_rate_limit_table(PDO $master): void
{
    $master->exec(
        "CREATE TABLE IF NOT EXISTS api_rate_limit_counters (
            id BIGINT AUTO_INCREMENT PRIMARY KEY,
            bucket_key VARCHAR(190) NOT NULL,
            window_start BIGINT NOT NULL,
            request_count INT NOT NULL DEFAULT 0,
            updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
            UNIQUE KEY uniq_bucket_window (bucket_key, window_start),
            KEY idx_window_start (window_start)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"
    );
}

function golder_rate_limit_allow(PDO $master, string $bucketKey, int $maxRequests, int $windowSeconds): bool
{
    golder_ensure_rate_limit_table($master);

    if ($maxRequests <= 0 || $windowSeconds <= 0) {
        return true;
    }

    $windowStart = (int)(floor(time() / $windowSeconds) * $windowSeconds);

    $master->beginTransaction();
    try {
        $st = $master->prepare(
            'SELECT id, request_count FROM api_rate_limit_counters WHERE bucket_key = :b AND window_start = :w LIMIT 1 FOR UPDATE'
        );
        $st->execute([':b' => $bucketKey, ':w' => $windowStart]);
        $row = $st->fetch();

        if (!$row) {
            $ins = $master->prepare(
                'INSERT INTO api_rate_limit_counters (bucket_key, window_start, request_count) VALUES (:b, :w, 1)'
            );
            $ins->execute([':b' => $bucketKey, ':w' => $windowStart]);
            $master->commit();
            return true;
        }

        $count = (int)($row['request_count'] ?? 0) + 1;
        $upd = $master->prepare('UPDATE api_rate_limit_counters SET request_count = :c WHERE id = :id');
        $upd->execute([':c' => $count, ':id' => (int)$row['id']]);
        $master->commit();

        return $count <= $maxRequests;
    } catch (Throwable $e) {
        if ($master->inTransaction()) {
            $master->rollBack();
        }
        return true;
    }
}

function golder_rate_limit_cleanup(PDO $master, int $keepHours = 72): int
{
    golder_ensure_rate_limit_table($master);
    $threshold = time() - max(1, $keepHours) * 3600;
    $st = $master->prepare('DELETE FROM api_rate_limit_counters WHERE window_start < :t');
    $st->execute([':t' => $threshold]);
    return (int)$st->rowCount();
}


