<?php
namespace App\Core;

class Security
{
    /**
     * Rate limiting robusto — armazenado na base de dados.
     * Ao contrário de $_SESSION, não é bypassável limpando cookies.
     *
     * @param  string $key    Chave única (ex: 'login_' . md5($ip))
     * @param  int    $max    Máximo de tentativas
     * @param  int    $window Janela em segundos
     * @return bool   true = permitido, false = bloqueado
     */
    public static function rateLimit(string $key, int $max = 10, int $window = 900): bool
    {
        try {
            $pdo  = Database::pdo();
            $now  = time();
            $rkey = \substr(\hash('sha256', $key), 0, 64);

            $row = $pdo->prepare("SELECT attempts, first_at FROM _rate_limits WHERE rkey=?");
            $row->execute([$rkey]);
            $data = $row->fetch(\PDO::FETCH_ASSOC);

            if (!$data) {
                // Primeira tentativa
                $pdo->prepare("INSERT INTO _rate_limits (rkey,attempts,first_at,last_at) VALUES (?,1,?,?)")
                    ->execute([$rkey, $now, $now]);
                return true;
            }

            // Expirou a janela — reset
            if ($now - $data['first_at'] > $window) {
                $pdo->prepare("UPDATE _rate_limits SET attempts=1, first_at=?, last_at=? WHERE rkey=?")
                    ->execute([$now, $now, $rkey]);
                return true;
            }

            // Dentro da janela
            if ((int)$data['attempts'] >= $max) {
                return false; // bloqueado
            }

            $pdo->prepare("UPDATE _rate_limits SET attempts=attempts+1, last_at=? WHERE rkey=?")
                ->execute([$now, $rkey]);
            return true;

        } catch (\Throwable $e) {
            // Se a BD falhar, não bloquear o utilizador
            return true;
        }
    }

    /**
     * Limpar rate limiting (após login com sucesso)
     */
    public static function rateLimitClear(string $key): void
    {
        try {
            $rkey = \substr(\hash('sha256', $key), 0, 64);
            Database::pdo()->prepare("DELETE FROM _rate_limits WHERE rkey=?")
                ->execute([$rkey]);
        } catch (\Throwable $e) {}
    }

    // Compatibilidade com código existente
    public static function checkLoginRate(string $ip): bool
    {
        return self::rateLimit('login_' . $ip, 10, 900);
    }

    public static function clearLoginRate(string $ip): void
    {
        self::rateLimitClear('login_' . $ip);
    }

    // Alias para compatibilidade com código existente
    public static function resetLoginRate(string $ip): void
    {
        self::rateLimitClear('login_' . $ip);
    }

    // Sanitizar input de texto simples
    public static function clean(string $value): string
    {
        return \trim(\strip_tags($value));
    }

    public static function sendHeaders(): void
    {
        \header_remove('X-Powered-By');
        \header('X-Content-Type-Options: nosniff');
        \header('X-Frame-Options: SAMEORIGIN');
    }
}
