<?php
require_once __DIR__ . '/../config/db.php';

class Firewall {
    private $db;
    private $ip;
    private $userAgent;

    public function __construct() {
        $database = new Database();
        $this->db = $database->getConnection();
        $this->ip = $_SERVER['REMOTE_ADDR'];
        $this->userAgent = $_SERVER['HTTP_USER_AGENT'] ?? '';
    }

    public function protect() {
        if ($this->isBlocked()) {
            header('HTTP/1.1 403 Forbidden');
            exit('Access Denied');
        }

        if ($this->isBot()) {
            $this->blockIp('Malicious Bot');
            header('HTTP/1.1 403 Forbidden');
            exit('Access Denied: Bot detected');
        }

        if ($this->isRateLimited()) {
            header('HTTP/1.1 429 Too Many Requests');
            exit('Too Many Requests');
        }
    }

    private function isBlocked() {
        $stmt = $this->db->prepare("SELECT id FROM blocked_ips WHERE ip_address = :ip AND (blocked_until IS NULL OR blocked_until > NOW())");
        $stmt->execute([':ip' => $this->ip]);
        return $stmt->rowCount() > 0;
    }

    private function isBot() {
        $badBots = [
            'SemrushBot', 'AhrefsBot', 'MJ12bot', 'DotBot', 'PetalBot', 'Bytespider', 
            'Barkrowler', 'Seekport', 'Serpstat', 'Zoominfo'
        ]; // Add more as needed

        foreach ($badBots as $bot) {
            if (stripos($this->userAgent, $bot) !== false) {
                return true;
            }
        }
        return false;
    }

    private function isRateLimited() {
        // Simple rate limiting: 100 requests per minute
        // We use a file-based approach for speed or DB? 
        // Let's use DB for persistence and since traffic isn't massive yet.
        // Ideally Redis, but we stick to MySQL as requested.
        
        // Clean up old logs first (optional, maybe cron job better)
        // $this->db->exec("DELETE FROM firewall_logs WHERE blocked_at < NOW() - INTERVAL 1 MINUTE");

        // Count requests in last minute
        // Note: We are not logging every request to DB to avoid overhead, 
        // but for rate limiting we need to track them. 
        // Let's use a separate table `request_tracker` or just use a file for this specific high-write op?
        // The old site used a file. Let's stick to a file for the counter to avoid DB thrashing, 
        // but use DB for the block list.
        
        $trackerFile = __DIR__ . '/../request_tracker.json';
        $data = [];
        if (file_exists($trackerFile)) {
            $data = json_decode(file_get_contents($trackerFile), true) ?? [];
        }

        // Cleanup old IPs
        foreach ($data as $ip => $info) {
            if (time() - $info['time'] > 60) {
                unset($data[$ip]);
            }
        }

        if (!isset($data[$this->ip])) {
            $data[$this->ip] = ['count' => 1, 'time' => time()];
        } else {
            $data[$this->ip]['count']++;
        }

        // Save
        file_put_contents($trackerFile, json_encode($data));

        if ($data[$this->ip]['count'] > 100) {
            $this->blockIp('Rate Limit Exceeded');
            return true;
        }

        return false;
    }

    public function blockIp($reason) {
        // Check if already blocked
        if (!$this->isBlocked()) {
            $stmt = $this->db->prepare("INSERT INTO blocked_ips (ip_address, reason, blocked_until) VALUES (:ip, :reason, NOW() + INTERVAL 1 HOUR)");
            $stmt->execute([':ip' => $this->ip, ':reason' => $reason]);
            
            // Log it
            $stmtLog = $this->db->prepare("INSERT INTO firewall_logs (ip_address, user_agent, reason, request_uri) VALUES (:ip, :ua, :reason, :uri)");
            $stmtLog->execute([
                ':ip' => $this->ip,
                ':ua' => $this->userAgent,
                ':reason' => $reason,
                ':uri' => $_SERVER['REQUEST_URI'] ?? ''
            ]);
        }
    }

    public function logVisit($page) {
        // Simple visitor tracking (1 hit per IP per hour to avoid bloating)
        $stmt = $this->db->prepare("SELECT id FROM visitors WHERE ip_address = :ip AND page_viewed = :page AND timestamp > NOW() - INTERVAL 1 HOUR");
        $stmt->execute([':ip' => $this->ip, ':page' => $page]);
        
        if ($stmt->rowCount() == 0) {
            $stmtInsert = $this->db->prepare("INSERT INTO visitors (ip_address, user_agent, page_viewed) VALUES (:ip, :ua, :page)");
            $stmtInsert->execute([
                ':ip' => $this->ip,
                ':ua' => $this->userAgent,
                ':page' => $page
            ]);
        }
    }
}
