<?php
class SecurityManager {
    private static $instance = null;
    private $sessionLifetime;
    private $csrfTokenExpiry;
    
    private function __construct() {
        $this->sessionLifetime = $_ENV['SESSION_LIFETIME'] ?? 1800; // 30 minutes default
        $this->csrfTokenExpiry = $_ENV['CSRF_TOKEN_EXPIRY'] ?? 3600; // 1 hour default
    }
    
    public static function getInstance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    public function initializeSecureSession() {
        // Configure session security settings
        ini_set('session.cookie_httponly', 1);
        ini_set('session.cookie_secure', isset($_SERVER['HTTPS']) ? 1 : 0);
        ini_set('session.cookie_samesite', 'Strict');
        ini_set('session.use_strict_mode', 1);
        ini_set('session.gc_maxlifetime', $this->sessionLifetime);
        
        // Set session name
        session_name('RECRUITMENT_SESSID');
        
        if (session_status() === PHP_SESSION_NONE) {
            session_start();
        }
        
        // Check session timeout
        $this->checkSessionTimeout();
        
        // Regenerate session ID periodically
        $this->regenerateSessionId();
    }
    
    private function checkSessionTimeout() {
        if (isset($_SESSION['last_activity'])) {
            if (time() - $_SESSION['last_activity'] > $this->sessionLifetime) {
                $this->destroySession();
                return false;
            }
        }
        $_SESSION['last_activity'] = time();
        return true;
    }
    
    private function regenerateSessionId() {
        if (!isset($_SESSION['last_regeneration'])) {
            $_SESSION['last_regeneration'] = time();
        } elseif (time() - $_SESSION['last_regeneration'] > 300) { // 5 minutes
            session_regenerate_id(true);
            $_SESSION['last_regeneration'] = time();
        }
    }
    
    public function destroySession() {
        $_SESSION = array();
        
        if (ini_get("session.use_cookies")) {
            $params = session_get_cookie_params();
            setcookie(session_name(), '', time() - 42000,
                $params["path"], $params["domain"],
                $params["secure"], $params["httponly"]
            );
        }
        
        session_destroy();
    }
    
    public function generateSecureCSRFToken() {
        if (!isset($_SESSION['csrf_token']) || !isset($_SESSION['csrf_token_time']) || 
            time() - $_SESSION['csrf_token_time'] > $this->csrfTokenExpiry) {
            $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
            $_SESSION['csrf_token_time'] = time();
        }
        return $_SESSION['csrf_token'];
    }
    
    public function validateCSRFToken($token) {
        if (!isset($_SESSION['csrf_token']) || !isset($_SESSION['csrf_token_time'])) {
            return false;
        }
        
        if (time() - $_SESSION['csrf_token_time'] > $this->csrfTokenExpiry) {
            unset($_SESSION['csrf_token']);
            unset($_SESSION['csrf_token_time']);
            return false;
        }
        
        return hash_equals($_SESSION['csrf_token'], $token);
    }
    
    public function addSecurityHeaders() {
        header('X-Content-Type-Options: nosniff');
        header('X-Frame-Options: DENY');
        header('X-XSS-Protection: 1; mode=block');
        header('Referrer-Policy: strict-origin-when-cross-origin');
        header('Permissions-Policy: geolocation=(), microphone=(), camera=()');
        
        if (isset($_SERVER['HTTPS'])) {
            header('Strict-Transport-Security: max-age=31536000; includeSubDomains');
        }
        
        // Basic CSP - adjust as needed for your application
        $csp = "default-src 'self'; ";
        $csp .= "script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com; ";
        $csp .= "style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com; ";
        $csp .= "img-src 'self' data:; ";
        $csp .= "font-src 'self' https://cdnjs.cloudflare.com; ";
        $csp .= "connect-src 'self'; ";
        $csp .= "frame-src 'none'";
        
        header("Content-Security-Policy: " . $csp);
    }
}

class RateLimiter {
    private $db;
    
    public function __construct($database) {
        $this->db = $database;
    }
    
    public function checkRateLimit($identifier, $action = 'login', $maxAttempts = 5, $timeWindow = 900) {
        try {
            $stmt = $this->db->prepare("
                SELECT COUNT(*) as attempts 
                FROM rate_limits 
                WHERE identifier = ? AND action = ? AND created_at > DATE_SUB(NOW(), INTERVAL ? SECOND)
            ");
            $stmt->execute([$identifier, $action, $timeWindow]);
            $result = $stmt->fetch();
            
            if ($result['attempts'] >= $maxAttempts) {
                return false;
            }
            
            return true;
        } catch (PDOException $e) {
            // If table doesn't exist or other DB error, allow access but log error
            error_log("Rate limiting error: " . $e->getMessage());
            return true;
        }
    }
    
    public function recordAttempt($identifier, $action = 'login') {
        try {
            $stmt = $this->db->prepare("
                INSERT INTO rate_limits (identifier, action, created_at) 
                VALUES (?, ?, NOW())
            ");
            $stmt->execute([$identifier, $action]);
        } catch (PDOException $e) {
            error_log("Rate limiting record error: " . $e->getMessage());
        }
    }
    
    public function clearAttempts($identifier, $action = 'login') {
        try {
            $stmt = $this->db->prepare("
                DELETE FROM rate_limits 
                WHERE identifier = ? AND action = ?
            ");
            $stmt->execute([$identifier, $action]);
        } catch (PDOException $e) {
            error_log("Rate limiting clear error: " . $e->getMessage());
        }
    }
    
    public function cleanupOldRecords($olderThan = 3600) {
        try {
            $stmt = $this->db->prepare("
                DELETE FROM rate_limits 
                WHERE created_at < DATE_SUB(NOW(), INTERVAL ? SECOND)
            ");
            $stmt->execute([$olderThan]);
        } catch (PDOException $e) {
            error_log("Rate limiting cleanup error: " . $e->getMessage());
        }
    }
}
?>