<?php
/**
 * Security Helper Functions
 * Provides CSRF protection, input sanitization, and security utilities
 */

class SecurityHelper {
    
    /**
     * Generate CSRF token
     */
    public static function generateToken() {
        if (empty($_SESSION['csrf_token'])) {
            $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
            $_SESSION['csrf_token_time'] = time();
        }
        return $_SESSION['csrf_token'];
    }
    
    /**
     * Verify CSRF token
     */
    public static function verifyToken($token) {
        if (!isset($_SESSION['csrf_token']) || !isset($_SESSION['csrf_token_time'])) {
            return false;
        }
        
        // Check token age (default 1 hour)
        $maxAge = EnvLoader::getInt('CSRF_TOKEN_LIFETIME', 3600);
        if (time() - $_SESSION['csrf_token_time'] > $maxAge) {
            return false;
        }
        
        return hash_equals($_SESSION['csrf_token'], $token);
    }
    
    /**
     * Get CSRF token field HTML
     */
    public static function tokenField() {
        $token = self::generateToken();
        return '<input type="hidden" name="csrf_token" value="' . htmlspecialchars($token) . '">';
    }
    
    /**
     * Validate CSRF token from POST request
     */
    public static function validatePost() {
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $token = $_POST['csrf_token'] ?? '';
            if (!self::verifyToken($token)) {
                http_response_code(403);
                die('Invalid CSRF token. Please refresh the page and try again.');
            }
        }
    }
    
    /**
     * Sanitize input string
     */
    public static function sanitize($input, $type = 'string') {
        switch ($type) {
            case 'string':
                return htmlspecialchars(trim($input), ENT_QUOTES, 'UTF-8');
            case 'email':
                return filter_var(trim($input), FILTER_SANITIZE_EMAIL);
            case 'int':
                return filter_var($input, FILTER_VALIDATE_INT);
            case 'float':
                return filter_var($input, FILTER_VALIDATE_FLOAT);
            case 'url':
                return filter_var(trim($input), FILTER_SANITIZE_URL);
            default:
                return htmlspecialchars(trim($input), ENT_QUOTES, 'UTF-8');
        }
    }
    
    /**
     * Validate password strength
     */
    public static function validatePassword($password) {
        $minLength = EnvLoader::getInt('PASSWORD_MIN_LENGTH', 8);
        
        if (strlen($password) < $minLength) {
            return ['valid' => false, 'message' => "Password must be at least $minLength characters"];
        }
        
        if (!preg_match('/[A-Z]/', $password)) {
            return ['valid' => false, 'message' => 'Password must contain at least one uppercase letter'];
        }
        
        if (!preg_match('/[a-z]/', $password)) {
            return ['valid' => false, 'message' => 'Password must contain at least one lowercase letter'];
        }
        
        if (!preg_match('/[0-9]/', $password)) {
            return ['valid' => false, 'message' => 'Password must contain at least one number'];
        }
        
        if (!preg_match('/[!@#$%^&*(),.?":{}|<>]/', $password)) {
            return ['valid' => false, 'message' => 'Password must contain at least one special character'];
        }
        
        return ['valid' => true, 'message' => 'Password is strong'];
    }
    
    /**
     * Generate secure random string
     */
    public static function randomString($length = 32) {
        return bin2hex(random_bytes($length / 2));
    }
    
    /**
     * Hash password securely
     */
    public static function hashPassword($password) {
        return password_hash($password, PASSWORD_ARGON2ID);
    }
    
    /**
     * Verify password
     */
    public static function verifyPassword($password, $hash) {
        return password_verify($password, $hash);
    }
    
    /**
     * Check if user has required role
     */
    public static function checkRole($requiredRole) {
        if (!isset($_SESSION['user_role'])) {
            return false;
        }
        
        $roleHierarchy = [
            'admin' => 4,
            'teacher' => 3,
            'student' => 2,
            'parent' => 1
        ];
        
        $userLevel = $roleHierarchy[$_SESSION['user_role']] ?? 0;
        $requiredLevel = $roleHierarchy[$requiredRole] ?? 0;
        
        return $userLevel >= $requiredLevel;
    }
    
    /**
     * Redirect if not authenticated
     */
    public static function requireAuth() {
        if (!isset($_SESSION['user_id'])) {
            header('Location: ' . BASE_URL . '/login.php');
            exit;
        }
    }
    
    /**
     * Redirect if not authorized for role
     */
    public static function requireRole($role) {
        self::requireAuth();
        if (!self::checkRole($role)) {
            http_response_code(403);
            die('Access denied. You do not have permission to access this page.');
        }
    }
    
    /**
     * Log security event
     */
    public static function logEvent($event, $details = []) {
        $logEntry = [
            'timestamp' => date('Y-m-d H:i:s'),
            'event' => $event,
            'user_id' => $_SESSION['user_id'] ?? null,
            'ip_address' => $_SERVER['REMOTE_ADDR'] ?? null,
            'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? null,
            'details' => $details
        ];
        
        $logFile = __DIR__ . '/../logs/security.log';
        $logDir = dirname($logFile);
        
        if (!is_dir($logDir)) {
            mkdir($logDir, 0755, true);
        }
        
        file_put_contents($logFile, json_encode($logEntry) . "\n", FILE_APPEND | LOCK_EX);
    }
    
    /**
     * Rate limiting check
     */
    public static function checkRateLimit($key, $maxAttempts = 5, $decayMinutes = 1) {
        $cacheFile = __DIR__ . '/../cache/ratelimit_' . md5($key) . '.json';
        $cacheDir = dirname($cacheFile);
        
        if (!is_dir($cacheDir)) {
            mkdir($cacheDir, 0755, true);
        }
        
        $attempts = [];
        if (file_exists($cacheFile)) {
            $attempts = json_decode(file_get_contents($cacheFile), true) ?: [];
        }
        
        $now = time();
        $window = $decayMinutes * 60;
        
        // Remove old attempts
        $attempts = array_filter($attempts, function($time) use ($now, $window) {
            return ($now - $time) < $window;
        });
        
        if (count($attempts) >= $maxAttempts) {
            return false;
        }
        
        $attempts[] = $now;
        file_put_contents($cacheFile, json_encode($attempts), LOCK_EX);
        
        return true;
    }
}

// Short helper functions
if (!function_exists('csrf_field')) {
    function csrf_field() {
        return SecurityHelper::tokenField();
    }
}

if (!function_exists('sanitize')) {
    function sanitize($input, $type = 'string') {
        return SecurityHelper::sanitize($input, $type);
    }
}

if (!function_exists('require_auth')) {
    function require_auth() {
        SecurityHelper::requireAuth();
    }
}

if (!function_exists('require_role')) {
    function require_role($role) {
        SecurityHelper::requireRole($role);
    }
}
?>
