<?php
/**
 * AUTO TESTER - Configuration File
 * Secure configuration management
 */

// Load environment variables from .env file FIRST (before defining constants)
if (file_exists(__DIR__ . '/.env')) {
    $lines = file(__DIR__ . '/.env', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
    foreach ($lines as $line) {
        $line = trim($line);
        if (empty($line) || str_starts_with($line, '#')) continue;
        
        if (strpos($line, '=') !== false) {
            list($key, $value) = explode('=', $line, 2);
            $key = trim($key);
            $value = trim($value);
            
            // Remove quotes if present
            if ((str_starts_with($value, '"') && str_ends_with($value, '"')) || 
                (str_starts_with($value, "'") && str_ends_with($value, "'"))) {
                $value = substr($value, 1, -1);
            }
            
            $_ENV[$key] = $value;
        }
    }
}

// PHP compatibility functions for older versions
if (!function_exists('str_starts_with')) {
    function str_starts_with($haystack, $needle) {
        return (string)$needle !== '' && strncmp($haystack, $needle, strlen($needle)) === 0;
    }
}

if (!function_exists('str_ends_with')) {
    function str_ends_with($haystack, $needle) {
        return $needle !== '' && substr($haystack, -strlen($needle)) === (string)$needle;
    }
}

if (!function_exists('random_int')) {
    function random_int($min, $max) {
        return mt_rand($min, $max);
    }
}

if (!function_exists('glob')) {
    function glob($pattern, $flags = 0) {
        // Return empty array if glob is not available
        return [];
    }
}

// Database configuration - NO DEFAULT PASSWORDS
define('DB_HOST', $_ENV['DB_HOST'] ?? 'localhost');
define('DB_NAME', $_ENV['DB_NAME'] ?? 'digitals_autotester_db');
define('DB_USER', $_ENV['DB_USER'] ?? 'autotes1_system');
define('DB_PASS', $_ENV['DB_PASS'] ?? 'bassam.bassam');

// Validate critical security settings
if (!defined('DB_PASS') || DB_PASS === null) {
    die('Database password is not configured. Please set DB_PASS in your .env file.');
}

// Application configuration
define('APP_NAME', 'AUTO TESTER');
define('APP_VERSION', '2.0');
define('APP_URL', $_ENV['APP_URL'] ?? 'http://localhost/autotestersystem111');

// Security configuration - NO DEFAULT SECRETS
define('JWT_SECRET', $_ENV['JWT_SECRET'] ?? null);
define('SESSION_LIFETIME', (int)($_ENV['SESSION_LIFETIME'] ?? 604800)); // 7 days in seconds
define('MAX_LOGIN_ATTEMPTS', (int)($_ENV['MAX_LOGIN_ATTEMPTS'] ?? 5));
define('LOGIN_LOCKOUT_TIME', (int)($_ENV['LOGIN_LOCKOUT_TIME'] ?? 900)); // 15 minutes

// Validate JWT secret
if (!defined('JWT_SECRET') || JWT_SECRET === null || JWT_SECRET === 'your-secret-key-here') {
    die('JWT_SECRET is not configured properly. Please set a strong random JWT_SECRET in your .env file.');
}

// CSRF Protection
define('CSRF_PROTECTION_ENABLED', filter_var($_ENV['CSRF_PROTECTION_ENABLED'] ?? 'true', FILTER_VALIDATE_BOOLEAN));
define('CSRF_TOKEN_LIFETIME', (int)($_ENV['CSRF_TOKEN_LIFETIME'] ?? 7200)); // 2 hours

// Rate Limiting
define('RATE_LIMIT_PER_IP', (int)($_ENV['RATE_LIMIT_PER_IP'] ?? 60)); // requests per minute
define('RATE_LIMIT_WINDOW', (int)($_ENV['RATE_LIMIT_WINDOW'] ?? 60)); // seconds

// Two Factor Authentication
define('TWO_FACTOR_AUTH_ENABLED', filter_var($_ENV['TWO_FACTOR_AUTH_ENABLED'] ?? 'true', FILTER_VALIDATE_BOOLEAN));

// File upload configuration
define('UPLOAD_PATH', __DIR__ . '/uploads/');
define('MAX_FILE_SIZE', 5 * 1024 * 1024); // 5MB
define('ALLOWED_FILE_TYPES', ['jpg', 'jpeg', 'png', 'gif', 'pdf']);

// Email configuration
define('SMTP_HOST', $_ENV['SMTP_HOST'] ?? 'localhost');
define('SMTP_PORT', $_ENV['SMTP_PORT'] ?? 587);
define('SMTP_USERNAME', $_ENV['SMTP_USERNAME'] ?? '');
define('SMTP_PASSWORD', $_ENV['SMTP_PASSWORD'] ?? '');
define('SMTP_FROM_EMAIL', $_ENV['SMTP_FROM_EMAIL'] ?? 'noreply@autotester.com');
define('SMTP_FROM_NAME', $_ENV['SMTP_FROM_NAME'] ?? 'AUTO TESTER');

// API configuration
define('API_RATE_LIMIT', 100); // requests per minute
define('API_TIMEOUT', 30); // seconds

// Blockchain configuration
define('BLOCKCHAIN_ENABLED', true);
define('BLOCKCHAIN_NODE_URL', $_ENV['BLOCKCHAIN_NODE_URL'] ?? 'http://localhost:8545');

// Logging configuration
define('LOG_PATH', __DIR__ . '/logs/');
define('LOG_LEVEL', $_ENV['LOG_LEVEL'] ?? 'INFO');
define('ERROR_LOG_FILE', LOG_PATH . 'error.log');
define('ACCESS_LOG_FILE', LOG_PATH . 'access.log');

// Cache configuration
define('CACHE_ENABLED', true);
define('CACHE_TTL', 3600); // 1 hour

// Development/Production mode
define('DEBUG_MODE', $_ENV['DEBUG_MODE'] ?? false);
define('MAINTENANCE_MODE', $_ENV['MAINTENANCE_MODE'] ?? false);

// Theme configuration
define('DEFAULT_THEME', 'light');
define('THEMES', ['light', 'dark', 'auto']);

// Language configuration
define('DEFAULT_LANGUAGE', 'ar');
define('SUPPORTED_LANGUAGES', ['ar', 'en']);

// Backup configuration
define('BACKUP_ENABLED', true);
define('BACKUP_PATH', __DIR__ . '/backups/');
define('BACKUP_SCHEDULE', 'daily');
define('BACKUP_RETENTION_DAYS', 30);

// API Keys (should be loaded from environment variables)
define('GOOGLE_MAPS_API_KEY', $_ENV['GOOGLE_MAPS_API_KEY'] ?? '');
define('OPENAI_API_KEY', $_ENV['OPENAI_API_KEY'] ?? '');
define('TWILIO_API_KEY', $_ENV['TWILIO_API_KEY'] ?? '');
define('TWILIO_API_SECRET', $_ENV['TWILIO_API_SECRET'] ?? '');

// Performance configuration
define('MAX_CONCURRENT_REQUESTS', 100);
define('MEMORY_LIMIT', '256M');
define('EXECUTION_TIME_LIMIT', 300); // 5 minutes

// Enhanced security headers
define('SECURITY_HEADERS', [
    'X-Frame-Options' => 'DENY',
    'X-Content-Type-Options' => 'nosniff',
    'X-XSS-Protection' => '1; mode=block',
    'Strict-Transport-Security' => 'max-age=31536000; includeSubDomains; preload',
    'Content-Security-Policy' => "default-src 'self'; script-src 'self' 'nonce-{nonce}'; style-src 'self'; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https:; connect-src 'self'; frame-ancestors 'none'; form-action 'self'; base-uri 'self'",
    'Referrer-Policy' => 'strict-origin-when-cross-origin',
    'Permissions-Policy' => 'geolocation=(), microphone=(), camera=(), payment=(), usb=(), magnetometer=(), gyroscope=()',
    'Cross-Origin-Embedder-Policy' => 'require-corp',
    'Cross-Origin-Opener-Policy' => 'same-origin',
    'Cross-Origin-Resource-Policy' => 'same-origin'
]);

// Error reporting based on environment
if (DEBUG_MODE) {
    error_reporting(E_ALL);
    ini_set('display_errors', 1);
} else {
    error_reporting(E_ERROR | E_WARNING | E_PARSE);
    ini_set('display_errors', 0);
    ini_set('log_errors', 1);
    ini_set('error_log', ERROR_LOG_FILE);
}

// Set default timezone
date_default_timezone_set('Africa/Cairo');

/**
 * Check if all required PHP extensions are loaded
 */
function checkRequiredExtensions() {
    $required = ['pdo_mysql', 'openssl', 'json', 'session', 'hash'];
    $missing = [];
    
    foreach ($required as $ext) {
        if (!extension_loaded($ext)) {
            $missing[] = $ext;
        }
    }
    
    if (!empty($missing)) {
        die('Missing required extensions: ' . implode(', ', $missing) . '. Please install them to continue.');
    }
}

// Check required extensions
checkRequiredExtensions();

// Initialize secure session
if (session_status() === PHP_SESSION_NONE) {
    session_start([
        'cookie_httponly' => true,
        'cookie_secure' => !DEBUG_MODE,
        'cookie_samesite' => 'Strict',
        'use_strict_mode' => true,
        'gc_maxlifetime' => SESSION_LIFETIME
    ]);
    
    // Check session size limit
    define('SESSION_MAX_DATA_SIZE', 4096); // 4KB recommended
    if (isset($_SESSION) && strlen(serialize($_SESSION)) > SESSION_MAX_DATA_SIZE) {
        logSecurityEvent('SESSION_SIZE_EXCEEDED', ['size' => strlen(serialize($_SESSION))], 'WARNING');
    }
}

// Ensure required directories exist
$required_dirs = [UPLOAD_PATH, LOG_PATH, BACKUP_PATH];
foreach ($required_dirs as $dir) {
    if (!file_exists($dir)) {
        mkdir($dir, 0755, true);
    }
}

/**
 * Get configuration value with fallback (safe for undefined constants)
 */
function getConfig($key, $default = null) {
    return $_ENV[$key] ?? (defined($key) ? constant($key) : $default);
}

/**
 * Check if maintenance mode is enabled
 */
function isMaintenanceMode() {
    return MAINTENANCE_MODE || file_exists(__DIR__ . '/.maintenance');
}

/**
 * Get database connection parameters
 */
function getDatabaseConfig() {
    return [
        'host' => DB_HOST,
        'dbname' => DB_NAME,
        'username' => DB_USER,
        'password' => DB_PASS,
        'charset' => 'utf8mb4'
    ];
}

/**
 * Enhanced configuration validation
 */
function validateConfig() {
    $errors = [];
    $warnings = [];
    
    // Check required database configuration
    if (empty(DB_HOST) || empty(DB_NAME) || empty(DB_USER)) {
        $errors[] = 'Database configuration is incomplete';
    }
    
    // Check password strength
    if (strlen(DB_PASS) < 12) {
        $errors[] = 'Database password must be at least 12 characters long';
    }
    
    // Check for common weak passwords
    $weakPasswords = ['password', '123456', 'admin', 'root', 'qwerty', 'bassam.bassam'];
    if (in_array(strtolower(DB_PASS), $weakPasswords)) {
        $errors[] = 'Database password is too weak - please use a strong unique password';
    }
    
    // Check JWT secret strength
    if (strlen(JWT_SECRET) < 32) {
        $errors[] = 'JWT_SECRET must be at least 32 characters long';
    }
    
    // Check required directories
    if (!is_writable(UPLOAD_PATH)) {
        $errors[] = 'Upload directory is not writable';
    }
    
    if (!is_writable(LOG_PATH)) {
        $errors[] = 'Log directory is not writable';
    }
    
    // Security warnings
    if (DEBUG_MODE && !isMaintenanceMode()) {
        $warnings[] = 'Debug mode should not be enabled in production';
    }
    
    // Check directory permissions
    if (is_writable(__DIR__) && !DEBUG_MODE) {
        $warnings[] = 'Installation directory is writable - recommended to set permissions to 755';
    }
    
    // Check if .env file is readable by web server
    $envFile = __DIR__ . '/.env';
    if (file_exists($envFile)) {
        $perms = fileperms($envFile) & 0777;
        if ($perms & 0x004) { // World readable
            $warnings[] = '.env file is world readable - run: chmod 600 .env';
        }
    }
    
    // Check APP_URL format
    if (!isValidUrl(APP_URL)) {
        $errors[] = 'APP_URL is not a valid URL';
    }
    
    // Check backup directory location
    if (strpos(BACKUP_PATH, __DIR__) === 0) {
        $warnings[] = 'Backup directory should be outside the web root for better security';
    }
    
    return ['errors' => $errors, 'warnings' => $warnings];
}

/**
 * Generate secure random string for secrets
 */
function generateSecureSecret($length = 32) {
    return bin2hex(random_bytes($length / 2));
}

/**
 * Apply security headers with nonce accessibility
 */
function applySecurityHeaders() {
    static $headersApplied = false;
    if ($headersApplied) return;
    
    // Store CSP nonce in global for views
    global $CSP_NONCE;
    
    foreach (SECURITY_HEADERS as $header => $value) {
        if ($header === 'Content-Security-Policy') {
            $CSP_NONCE = bin2hex(random_bytes(16));
            $value = str_replace('{nonce}', $CSP_NONCE, $value);
            header("$header: $value", false);
        } else {
            header("$header: $value", false);
        }
    }
    
    $headersApplied = true;
}

/**
 * Fallback rate limiting using files (when APCu is not available)
 */
function fallbackRateLimit($key, $limit, $window) {
    $cacheDir = getCacheDir() . '/rate_limit';
    if (!file_exists($cacheDir)) {
        mkdir($cacheDir, 0755, true);
    }
    
    $cacheFile = $cacheDir . '/' . md5($key) . '.cache';
    $current = 0;
    $currentTime = time();
    
    if (file_exists($cacheFile)) {
        $data = json_decode(file_get_contents($cacheFile), true);
        if ($data && ($currentTime - $data['timestamp']) < $window) {
            $current = $data['count'];
        }
    }
    
    if ($current >= $limit) {
        http_response_code(429);
        die('Rate limit exceeded');
    }
    
    file_put_contents($cacheFile, json_encode([
        'count' => $current + 1,
        'timestamp' => $currentTime
    ]), LOCK_EX);
}

/**
 * Rate limiting helper with APCu fallback
 */
function checkRateLimit($ip, $limit = null, $window = null) {
    $limit = $limit ?? RATE_LIMIT_PER_IP;
    $window = $window ?? RATE_LIMIT_WINDOW;
    
    if (function_exists('apcu_fetch')) {
        $cacheKey = "rate_limit_" . md5($ip);
        $current = apcu_fetch($cacheKey) ?: 0;
        
        if ($current >= $limit) {
            http_response_code(429);
            die('Rate limit exceeded');
        }
        
        apcu_store($cacheKey, $current + 1, $window);
    } else {
        fallbackRateLimit($ip, $limit, $window);
    }
}

/**
 * CSRF token generation with session check
 */
function generateCSRFToken() {
    if (!CSRF_PROTECTION_ENABLED) return null;
    
    if (session_status() !== PHP_SESSION_ACTIVE) {
        error_log('CSRF token generation attempted without active session');
        return null;
    }
    
    $token = bin2hex(random_bytes(32));
    $_SESSION['csrf_token'] = $token;
    $_SESSION['csrf_token_time'] = time();
    return $token;
}

/**
 * Validate CSRF token with proper error handling
 */
function validateCSRFToken($token) {
    if (!CSRF_PROTECTION_ENABLED) return true;
    
    if (session_status() !== PHP_SESSION_ACTIVE) {
        return false;
    }
    
    if (!isset($_SESSION['csrf_token']) || !isset($_SESSION['csrf_token_time'])) {
        return false;
    }
    
    if (time() - $_SESSION['csrf_token_time'] > CSRF_TOKEN_LIFETIME) {
        unset($_SESSION['csrf_token'], $_SESSION['csrf_token_time']);
        return false;
    }
    
    return hash_equals($_SESSION['csrf_token'], $token);
}

/**
 * Log security events with structured data
 */
function logSecurityEvent($event, $details = [], $severity = 'INFO') {
    $logEntry = [
        'timestamp' => date('Y-m-d H:i:s'),
        'event' => $event,
        'severity' => $severity,
        'ip' => $_SERVER['REMOTE_ADDR'] ?? 'unknown',
        'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'unknown',
        'session_id' => session_id() ?: 'no-session',
        'details' => $details
    ];
    
    $logFile = LOG_PATH . 'security.log';
    $logLine = json_encode($logEntry) . PHP_EOL;
    
    // Ensure log directory exists
    if (!file_exists(LOG_PATH)) {
        mkdir(LOG_PATH, 0755, true);
    }
    
    file_put_contents($logFile, $logLine, FILE_APPEND | LOCK_EX);
    
    // Also log to error_log for critical events
    if (in_array($severity, ['CRITICAL', 'ERROR'])) {
        error_log("Security {$severity}: {$event} - " . json_encode($details));
    }
}


/**
 * Regenerate session ID securely with CSRF token regeneration
 */
function regenerateSession() {
    if (session_status() === PHP_SESSION_ACTIVE) {
        session_regenerate_id(true);
        // Update validation data
        $_SESSION['ip_address'] = $_SERVER['REMOTE_ADDR'];
        $_SESSION['user_agent'] = $_SERVER['HTTP_USER_AGENT'] ?? '';
        
        // Regenerate CSRF token after session change
        if (CSRF_PROTECTION_ENABLED) {
            $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
            $_SESSION['csrf_token_time'] = time();
        }
        
        logSecurityEvent('SESSION_REGENERATED', [
            'new_session_id' => session_id()
        ], 'INFO');
    }
}

// Validate configuration first (before any output)
$configValidation = validateConfig();
$configErrors = $configValidation['errors'];
$configWarnings = $configValidation['warnings'];

// Log all issues
if (!empty($configErrors)) {
    error_log('Configuration errors: ' . implode(', ', $configErrors));
}

if (!empty($configWarnings)) {
    error_log('Configuration warnings: ' . implode(', ', $configWarnings));
}

// Apply security headers immediately (before any HTML output)
applySecurityHeaders();

// Now it's safe to output HTML for debug mode
if (!empty($configErrors) && DEBUG_MODE) {
    echo '<div style="background: #f8d7da; color: #721c24; padding: 10px; margin: 10px; font-family: Arial, sans-serif;">';
    echo '<strong>Configuration Errors:</strong><br>';
    echo implode('<br>', $configErrors);
    echo '</div>';
}

if (!empty($configWarnings) && DEBUG_MODE) {
    echo '<div style="background: #fff3cd; color: #856404; padding: 10px; margin: 10px; font-family: Arial, sans-serif;">';
    echo '<strong>Configuration Warnings:</strong><br>';
    echo implode('<br>', $configWarnings);
    echo '</div>';
}

/**
 * Get writable cache directory with fallback options
 */
function getCacheDir() {
    $possibleDirs = [
        sys_get_temp_dir(),
        __DIR__ . '/cache',
        '/tmp'
    ];
    
    foreach ($possibleDirs as $dir) {
        if (is_writable($dir) || (!file_exists($dir) && @mkdir($dir, 0755, true))) {
            return rtrim($dir, '/') . '/autotester_cache';
        }
    }
    
    // Fallback to a directory within the application
    $fallbackDir = __DIR__ . '/cache';
    if (!file_exists($fallbackDir)) {
        mkdir($fallbackDir, 0755, true);
    }
    return $fallbackDir . '/autotester_cache';
}

/**
 * Simple file-based caching implementation
 */
function setCache($key, $value, $ttl = null) {
    if (!CACHE_ENABLED) return false;
    
    $ttl = $ttl ?? CACHE_TTL;
    $cacheDir = getCacheDir();
    if (!file_exists($cacheDir)) {
        mkdir($cacheDir, 0755, true);
    }
    
    $cacheFile = $cacheDir . '/' . md5($key) . '.cache';
    $data = [
        'value' => $value,
        'expires' => time() + $ttl
    ];
    
    return file_put_contents($cacheFile, json_encode($data), LOCK_EX) !== false;
}

function getCache($key, $default = null) {
    if (!CACHE_ENABLED) return $default;
    
    $cacheDir = getCacheDir();
    $cacheFile = $cacheDir . '/' . md5($key) . '.cache';
    
    if (!file_exists($cacheFile)) {
        return $default;
    }
    
    $data = json_decode(file_get_contents($cacheFile), true);
    if (!$data || time() > $data['expires']) {
        unlink($cacheFile);
        return $default;
    }
    
    return $data['value'];
}

/**
 * API rate limiting middleware
 */
function applyApiRateLimit($endpoint = null) {
    $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
    $limit = defined('API_RATE_LIMIT') ? API_RATE_LIMIT : RATE_LIMIT_PER_IP;
    $window = RATE_LIMIT_WINDOW;
    
    // Create a unique key per endpoint and IP
    $uniqueKey = $endpoint ? "api_{$endpoint}_{$ip}" : "api_global_{$ip}";
    
    if (function_exists('apcu_fetch')) {
        $current = apcu_fetch($uniqueKey) ?: 0;
        if ($current >= $limit) {
            http_response_code(429);
            die('API rate limit exceeded. Please try again later.');
        }
        apcu_store($uniqueKey, $current + 1, $window);
    } else {
        fallbackRateLimit($uniqueKey, $limit, $window);
    }
}

/**
 * Simple blockchain hash generation for integrity
 */
function generateBlockchainHash($data) {
    if (!BLOCKCHAIN_ENABLED) return null;
    
    if (is_array($data)) {
        $data = json_encode($data, JSON_SORT_KEYS);
    }
    
    // Create a simple hash chain: previous_hash + timestamp + data
    $previousHash = getCache('blockchain_previous_hash', '0');
    $timestamp = time();
    $content = $previousHash . $timestamp . $data;
    
    $hash = hash('sha256', $content);
    
    // Store current hash as previous for next block
    setCache('blockchain_previous_hash', $hash, 86400); // Store for 24 hours
    
    return [
        'hash' => $hash,
        'timestamp' => $timestamp,
        'previous_hash' => $previousHash
    ];
}

/**
 * Verify blockchain integrity
 */
function verifyBlockchainHash($data, $expectedHash, $timestamp, $previousHash) {
    if (!BLOCKCHAIN_ENABLED) return true;
    
    $content = $previousHash . $timestamp . (is_array($data) ? json_encode($data, JSON_SORT_KEYS) : $data);
    $calculatedHash = hash('sha256', $content);
    
    return hash_equals($calculatedHash, $expectedHash);
}

/**
 * Enhanced session validation with flexible IP checking
 */
function validateSession($strictIpCheck = false) {
    if (session_status() !== PHP_SESSION_ACTIVE) {
        return false;
    }
    
    // Initialize session validation data
    if (!isset($_SESSION['ip_address'])) {
        $_SESSION['ip_address'] = $_SERVER['REMOTE_ADDR'];
        $_SESSION['user_agent'] = $_SERVER['HTTP_USER_AGENT'] ?? '';
        $_SESSION['created_at'] = time();
        return true;
    }
    
    // Check user agent (always strict)
    $currentUA = $_SERVER['HTTP_USER_AGENT'] ?? '';
    if ($_SESSION['user_agent'] !== $currentUA) {
        logSecurityEvent('SESSION_UA_MISMATCH', [
            'expected_ua' => substr($_SESSION['user_agent'], 0, 100),
            'actual_ua' => substr($currentUA, 0, 100)
        ], 'WARNING');
        session_destroy();
        return false;
    }
    
    // Check IP address (flexible for mobile users)
    if ($_SESSION['ip_address'] !== $_SERVER['REMOTE_ADDR']) {
        if ($strictIpCheck) {
            logSecurityEvent('SESSION_IP_MISMATCH', [
                'expected_ip' => $_SESSION['ip_address'],
                'actual_ip' => $_SERVER['REMOTE_ADDR']
            ], 'WARNING');
            session_destroy();
            return false;
        } else {
            // Log the change but don't destroy session for mobile users
            logSecurityEvent('SESSION_IP_CHANGED', [
                'old_ip' => $_SESSION['ip_address'],
                'new_ip' => $_SERVER['REMOTE_ADDR']
            ], 'INFO');
            $_SESSION['ip_address'] = $_SERVER['REMOTE_ADDR']; // Update to new IP
        }
    }
    
    // Check session age
    $maxSessionAge = SESSION_LIFETIME;
    if (time() - $_SESSION['created_at'] > $maxSessionAge) {
        logSecurityEvent('SESSION_EXPIRED', [
            'session_age' => time() - $_SESSION['created_at'],
            'max_age' => $maxSessionAge
        ], 'INFO');
        session_destroy();
        return false;
    }
    
    return true;
}

/**
 * Check environment security
 */
function checkEnvironmentSecurity() {
    $issues = [];
    
    // Check HTTPS in production
    if (!DEBUG_MODE && empty($_SERVER['HTTPS'])) {
        $issues[] = 'HTTPS is not enabled - all data is transmitted in plain text';
    }
    
    // Check PHP version
    if (version_compare(PHP_VERSION, '7.4.0', '<')) {
        $issues[] = 'PHP version ' . PHP_VERSION . ' is no longer supported. Please upgrade to PHP 7.4+';
    }
    
    // Check for dangerous PHP settings
    $dangerousSettings = [
        'allow_url_fopen' => 'Off',
        'allow_url_include' => 'Off',
        'expose_php' => 'Off',
        'display_errors' => 'Off'
    ];
    
    foreach ($dangerousSettings as $setting => $recommended) {
        $current = ini_get($setting);
        if ($current != $recommended) {
            $issues[] = "PHP setting '$setting' is set to '$current', recommended: '$recommended'";
        }
    }
    
    return $issues;
}

/**
 * Test database connection with retry logic
 */
function testDatabaseConnection($retries = 3) {
    for ($i = 0; $i < $retries; $i++) {
        try {
            $config = getDatabaseConfig();
            $pdo = new PDO(
                "mysql:host={$config['host']};dbname={$config['dbname']};charset={$config['charset']}",
                $config['username'],
                $config['password'],
                [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
            );
            return true;
        } catch (PDOException $e) {
            if ($i === $retries - 1) {
                logSecurityEvent('DB_CONNECTION_FAILED', [
                    'host' => $config['host'],
                    'error' => $e->getMessage()
                ], 'CRITICAL');
                return false;
            }
            sleep(1); // Wait before retry
        }
    }
    return false;
}

/**
 * Clean up old cache files and logs
 */
function cleanupOldResources() {
    $now = time();
    
    // Clean old cache files
    $cacheDir = getCacheDir();
    if (file_exists($cacheDir)) {
        $files = glob($cacheDir . '/*.cache');
        foreach ($files as $file) {
            if ($now - filemtime($file) > 86400 * 7) { // Older than 7 days
                unlink($file);
            }
        }
    }
    
    // Clean old rate limit files
    $rateLimitDir = getCacheDir() . '/rate_limit';
    if (file_exists($rateLimitDir)) {
        $files = glob($rateLimitDir . '/*.cache');
        foreach ($files as $file) {
            if ($now - filemtime($file) > 86400) { // Older than 1 day
                unlink($file);
            }
        }
    }
    
    // Clean old logs (older than 30 days)
    if (defined('LOG_PATH') && file_exists(LOG_PATH)) {
        $logFiles = glob(LOG_PATH . '*.log');
        foreach ($logFiles as $file) {
            if ($now - filemtime($file) > 86400 * 30) {
                unlink($file);
            }
        }
    }
}

/**
 * Get system information for debugging
 */
function getSystemInfo() {
    return [
        'php_version' => PHP_VERSION,
        'server_software' => $_SERVER['SERVER_SOFTWARE'] ?? 'unknown',
        'extensions' => get_loaded_extensions(),
        'memory_limit' => ini_get('memory_limit'),
        'max_execution_time' => ini_get('max_execution_time'),
        'upload_max_filesize' => ini_get('upload_max_filesize'),
        'post_max_size' => ini_get('post_max_size'),
        'session_save_path' => session_save_path(),
        'cache_driver' => function_exists('apcu_fetch') ? 'APCu' : (CACHE_ENABLED ? 'File' : 'Disabled'),
        'cache_dir' => getCacheDir(),
        'debug_mode' => DEBUG_MODE,
        'app_version' => APP_VERSION,
        'session_status' => session_status(),
        'timezone' => date_default_timezone_get()
    ];
}

/**
 * Validate that all security keys are properly set
 */
function validateSecurityKeys() {
    $keys = [
        'JWT_SECRET' => JWT_SECRET,
        'DB_PASS' => DB_PASS,
    ];
    
    $weakKeys = [];
    foreach ($keys as $key => $value) {
        // Check if key is a default or weak value
        if (in_array(strtolower($value), ['your-secret-key-here', 'password', '123456', 'admin'])) {
            $weakKeys[] = $key;
        }
        
        // Check length for certain keys
        if ($key === 'JWT_SECRET' && strlen($value) < 32) {
            $weakKeys[] = $key . ' (too short: ' . strlen($value) . ' chars)';
        }
        
        if ($key === 'DB_PASS' && strlen($value) < 12) {
            $weakKeys[] = $key . ' (too short: ' . strlen($value) . ' chars)';
        }
    }
    
    if (!empty($weakKeys) && DEBUG_MODE) {
        echo '<div style="background: #f8d7da; color: #721c24; padding: 10px; margin: 10px; font-family: Arial, sans-serif;">';
        echo '<strong>Weak Security Keys:</strong><br>';
        echo 'The following keys should be strengthened: ' . implode(', ', $weakKeys);
        echo '</div>';
        logSecurityEvent('WEAK_SECURITY_KEYS', ['weak_keys' => $weakKeys], 'WARNING');
    }
    
    return empty($weakKeys);
}

/**
 * Validate and sanitize IP address
 */
function validateIpAddress($ip) {
    $ip = trim($ip);
    return filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6) ? $ip : null;
}

/**
 * Validate application URL format
 */
function isValidUrl($url) {
    return filter_var($url, FILTER_VALIDATE_URL) !== false;
}

/**
 * Generate secure keys for configuration
 */
function generateSecureKey($type = 'jwt') {
    switch ($type) {
        case 'jwt':
            return bin2hex(random_bytes(32)); // 64 characters
        case 'encryption':
            return base64_encode(random_bytes(32)); // 44 characters
        case 'api':
            return bin2hex(random_bytes(16)); // 32 characters
        default:
            return bin2hex(random_bytes(24));
    }
}

// Run environment security check in debug mode
if (DEBUG_MODE) {
    $envIssues = checkEnvironmentSecurity();
    if (!empty($envIssues)) {
        echo '<div style="background: #fff3cd; color: #856404; padding: 10px; margin: 10px; font-family: Arial, sans-serif;">';
        echo '<strong>Environment Security Issues:</strong><br>';
        echo implode('<br>', $envIssues);
        echo '</div>';
        error_log('Environment security issues: ' . implode(', ', $envIssues));
    }
}

// Validate security keys
validateSecurityKeys();

// Run cleanup periodically (1% chance)
if (random_int(1, 100) === 1) {
    cleanupOldResources();
}

// Quick self-test (only in debug mode when accessing config.php directly)
if (DEBUG_MODE && basename($_SERVER['PHP_SELF']) === 'config.php') {
    echo '<hr><h3>Configuration Self-Test</h3>';
    
    $tests = [
        'PHP Version' => version_compare(PHP_VERSION, '7.4.0', '>='),
        'Database Config' => (DB_HOST && DB_NAME && DB_USER && DB_PASS),
        'JWT Secret Length' => strlen(JWT_SECRET) >= 32,
        'Cache Directory Writable' => is_writable(getCacheDir()),
        'Log Directory Writable' => is_writable(LOG_PATH),
        'Upload Directory Writable' => is_writable(UPLOAD_PATH),
        'Session Active' => session_status() === PHP_SESSION_ACTIVE,
        'HTTPS Enabled (Production)' => !DEBUG_MODE ? (!empty($_SERVER['HTTPS'])) : true
    ];
    
    echo '<table border="1" cellpadding="8" style="border-collapse: collapse;">';
    foreach ($tests as $test => $result) {
        $color = $result ? 'green' : 'red';
        echo "<tr><td>{$test}</td><td style='color: {$color}; font-weight: bold;'>" . ($result ? 'PASS' : 'FAIL') . "</td></tr>";
    }
    echo '</table>';
    
    if (function_exists('testDatabaseConnection')) {
        echo '<h4>Database Connection Test:</h4>';
        echo testDatabaseConnection() ? '<span style="color: green;">Connected successfully</span>' : '<span style="color: red;">Connection failed</span>';
    }
}

?>
