<?php

namespace Gestoreasy\Core\Security;

use PDO;
use Gestoreasy\Core\Admin\ConnectionManager as AdminDb;

/**
 * Proteção contra ataques de força bruta
 */
class BruteForceProtection {
    
    private const MAX_ATTEMPTS = 5; // Máximo de tentativas
    private const LOCKOUT_DURATION = 900; // 15 minutos em segundos
    private const CLEANUP_INTERVAL = 3600; // 1 hora em segundos
    
    /**
     * Verifica se o IP está bloqueado
     */
    public static function isBlocked(string $ip, string $type = 'login'): bool {
        $pdo = AdminDb::db();
        
        // Limpar registros antigos periodicamente
        self::cleanup($pdo);
        
        $stmt = $pdo->prepare('
            SELECT COUNT(*) as attempts, MAX(attempted_at) as last_attempt
            FROM brute_force_attempts
            WHERE ip_address = ? AND type = ? AND attempted_at > DATE_SUB(NOW(), INTERVAL ? SECOND)
        ');
        $stmt->execute([$ip, $type, self::LOCKOUT_DURATION]);
        $result = $stmt->fetch();
        
        if ($result && (int)$result['attempts'] >= self::MAX_ATTEMPTS) {
            return true;
        }
        
        return false;
    }
    
    /**
     * Registra uma tentativa falhada
     */
    public static function recordFailedAttempt(string $ip, string $type = 'login', ?string $identifier = null): void {
        $pdo = AdminDb::db();
        
        $stmt = $pdo->prepare('
            INSERT INTO brute_force_attempts (ip_address, type, identifier, attempted_at)
            VALUES (?, ?, ?, NOW())
        ');
        $stmt->execute([$ip, $type, $identifier]);
    }
    
    /**
     * Limpa tentativas antigas
     */
    private static function cleanup(PDO $pdo): void {
        // Limpar apenas uma vez por hora (usando cache ou timestamp)
        $lastCleanup = self::getLastCleanupTime();
        if (time() - $lastCleanup < self::CLEANUP_INTERVAL) {
            return;
        }
        
        $stmt = $pdo->prepare('
            DELETE FROM brute_force_attempts
            WHERE attempted_at < DATE_SUB(NOW(), INTERVAL ? SECOND)
        ');
        $stmt->execute([self::LOCKOUT_DURATION * 2]);
        
        self::setLastCleanupTime();
    }
    
    /**
     * Obtém o tempo da última limpeza
     */
    private static function getLastCleanupTime(): int {
        $file = sys_get_temp_dir() . '/gestoreasy_bruteforce_cleanup.txt';
        if (file_exists($file)) {
            return (int)file_get_contents($file);
        }
        return 0;
    }
    
    /**
     * Define o tempo da última limpeza
     */
    private static function setLastCleanupTime(): void {
        $file = sys_get_temp_dir() . '/gestoreasy_bruteforce_cleanup.txt';
        file_put_contents($file, (string)time());
    }
    
    /**
     * Limpa tentativas de um IP específico (após login bem-sucedido)
     */
    public static function clearAttempts(string $ip, string $type = 'login'): void {
        $pdo = AdminDb::db();
        
        $stmt = $pdo->prepare('
            DELETE FROM brute_force_attempts
            WHERE ip_address = ? AND type = ?
        ');
        $stmt->execute([$ip, $type]);
    }
    
    /**
     * Obtém o tempo restante de bloqueio em segundos
     */
    public static function getRemainingLockoutTime(string $ip, string $type = 'login'): int {
        $pdo = AdminDb::db();
        
        $stmt = $pdo->prepare('
            SELECT MAX(attempted_at) as last_attempt
            FROM brute_force_attempts
            WHERE ip_address = ? AND type = ?
        ');
        $stmt->execute([$ip, $type]);
        $result = $stmt->fetch();
        
        if (!$result || !$result['last_attempt']) {
            return 0;
        }
        
        $lastAttempt = strtotime($result['last_attempt']);
        $lockoutEnd = $lastAttempt + self::LOCKOUT_DURATION;
        $remaining = $lockoutEnd - time();
        
        return max(0, $remaining);
    }
}

