<?php
/**
 * RateLimiter — simple file-based, key-scoped rate limiting shared by
 * every auth entry point that needs it (Sign In, Sign Up), generalizing
 * the same file-based-per-IP technique api/auth/forgot-password.php
 * already established on its own.
 *
 * Deliberately NOT session-based: index.php's own global API throttle
 * keys off $_SESSION, which an attacker can reset for free by dropping
 * cookies between requests. This persists on disk across requests
 * regardless of cookies/session, so it actually slows down a scripted
 * attacker, not just a browser with cookies enabled.
 *
 * Not a substitute for a real shared store (Redis/etc.) behind a
 * multi-server production deployment — it's local-disk, per-app-server
 * state, same honestly-scoped caveat forgot-password.php's own comment
 * already carries ("upgrade to Redis/memcached in production").
 */
class RateLimiter
{
    private static function dir(): string
    {
        $dir = sys_get_temp_dir() . '/traderalign_rate_limits';
        if (!is_dir($dir)) {
            @mkdir($dir, 0755, true);
        }
        return $dir;
    }

    /**
     * Records this attempt and reports whether the caller is still within
     * the allowed rate. The attempt is recorded even when the limit has
     * already been exceeded, so repeated retries don't reset the window.
     */
    public static function attempt(string $key, int $maxAttempts, int $windowSeconds): bool
    {
        $file = self::dir() . '/' . hash('sha256', $key) . '.json';

        $data = [];
        if (is_file($file)) {
            $raw = @file_get_contents($file);
            if ($raw !== false) {
                $decoded = json_decode($raw, true);
                if (is_array($decoded)) {
                    $data = $decoded;
                }
            }
        }

        $cutoff = time() - $windowSeconds;
        $data = array_values(array_filter($data, static fn($ts) => is_numeric($ts) && $ts > $cutoff));

        $allowed = count($data) < $maxAttempts;

        $data[] = time();
        @file_put_contents($file, json_encode($data), LOCK_EX);

        return $allowed;
    }
}
