<?php
/**
 * Security Configuration for Al-Runan Llumar Fitment Centre
 * 
 * This file contains security-related settings and functions.
 */

// Security configuration constants
define('SECURITY_SALT', 'al_runan_secure_salt_2024_change_in_production');
define('SESSION_TIMEOUT', 3600); // 1 hour in seconds
define('MAX_LOGIN_ATTEMPTS', 5);
define('LOCKOUT_DURATION', 900); // 15 minutes in seconds
define('PASSWORD_MIN_LENGTH', 8);
define('PASSWORD_REQUIRE_UPPERCASE', true);
define('PASSWORD_REQUIRE_LOWERCASE', true);
define('PASSWORD_REQUIRE_NUMBERS', true);
define('PASSWORD_REQUIRE_SYMBOLS', true);

/**
 * Security utility functions
 */
class Security {
    
    /**
     * Generate a secure random token
     */
    public static function generateToken($length = 32) {
        return bin2hex(random_bytes($length));
    }
    
    /**
     * Hash data with application salt
     */
    public static function hashData($data) {
        return hash_hmac('sha256', $data, SECURITY_SALT);
    }
    
    /**
     * Encrypt data using OpenSSL
     */
    public static function encrypt($data, $key = null) {
        if ($key === null) {
            $key = SECURITY_SALT;
        }
        
        $method = 'AES-256-CBC';
        $iv_length = openssl_cipher_iv_length($method);
        $iv = openssl_random_pseudo_bytes($iv_length);
        
        $encrypted = openssl_encrypt($data, $method, $key, 0, $iv);
        return base64_encode($iv . $encrypted);
    }
    
    /**
     * Decrypt data using OpenSSL
     */
    public static function decrypt($data, $key = null) {
        if ($key === null) {
            $key = SECURITY_SALT;
        }
        
        $method = 'AES-256-CBC';
        $data = base64_decode($data);
        $iv_length = openssl_cipher_iv_length($method);
        $iv = substr($data, 0, $iv_length);
        $encrypted = substr($data, $iv_length);
        
        return openssl_decrypt($encrypted, $method, $key, 0, $iv);
    }
    
    /**
     * Sanitize file name to prevent directory traversal
     */
    public static function sanitizeFileName($filename) {
        // Remove path traversal characters
        $filename = str_replace(['../', '..\\', '/', '\\'], '', $filename);
        
        // Remove null bytes
        $filename = str_replace("\0", '', $filename);
        
        // Limit length
        $filename = substr($filename, 0, 255);
        
        return $filename;
    }
    
    /**
     * Validate and sanitize file upload
     */
    public static function validateUploadedFile($file, $allowed_types = [], $max_size = 5242880) {
        $errors = [];
        
        // Check for upload errors
        if ($file['error'] !== UPLOAD_ERR_OK) {
            $errors[] = 'File upload error: ' . $file['error'];
            return [false, $errors];
        }
        
        // Check file size
        if ($file['size'] > $max_size) {
            $errors[] = 'File size exceeds maximum allowed size';
        }
        
        // Check file type
        $file_info = finfo_open(FILEINFO_MIME_TYPE);
        $mime_type = finfo_file($file_info, $file['tmp_name']);
        finfo_close($file_info);
        
        if (!empty($allowed_types) && !in_array($mime_type, $allowed_types)) {
            $errors[] = 'File type not allowed';
        }
        
        // Check for malicious files
        $dangerous_extensions = ['php', 'phtml', 'php3', 'php4', 'php5', 'phar'];
        $file_extension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
        
        if (in_array($file_extension, $dangerous_extensions)) {
            $errors[] = 'Potentially dangerous file type';
        }
        
        return [empty($errors), $errors];
    }
    
    /**
     * Prevent SQL injection by escaping user input
     */
    public static function escapeSql($db, $data) {
        if (is_array($data)) {
            foreach ($data as $key => $value) {
                $data[$key] = self::escapeSql($db, $value);
            }
            return $data;
        }
        
        return $db->quote($data);
    }
    
    /**
     * Generate CSRF token for forms
     */
    public static function generateCsrfToken() {
        if (session_status() === PHP_SESSION_NONE) {
            session_start();
        }
        
        $token = self::generateToken();
        $_SESSION['csrf_token'] = $token;
        $_SESSION['csrf_token_time'] = time();
        
        return $token;
    }
    
    /**
     * Validate CSRF token
     */
    public static function validateCsrfToken($token, $timeout = 3600) {
        if (session_status() === PHP_SESSION_NONE) {
            session_start();
        }
        
        if (!isset($_SESSION['csrf_token']) || !isset($_SESSION['csrf_token_time'])) {
            return false;
        }
        
        if ($_SESSION['csrf_token'] !== $token) {
            return false;
        }
        
        if (time() - $_SESSION['csrf_token_time'] > $timeout) {
            unset($_SESSION['csrf_token'], $_SESSION['csrf_token_time']);
            return false;
        }
        
        return true;
    }
    
    /**
     * Rate limiting function
     */
    public static function rateLimit($key, $max_attempts, $time_window) {
        $cache_file = __DIR__ . '/../cache/rate_limit_' . md5($key) . '.json';
        $now = time();
        
        if (file_exists($cache_file)) {
            $data = json_decode(file_get_contents($cache_file), true);
            
            // Clean old entries
            $data['attempts'] = array_filter($data['attempts'], function($timestamp) use ($now, $time_window) {
                return ($now - $timestamp) < $time_window;
            });
        } else {
            $data = ['attempts' => []];
        }
        
        // Add current attempt
        $data['attempts'][] = $now;
        
        // Check if limit exceeded
        $attempts_count = count($data['attempts']);
        $is_limited = $attempts_count > $max_attempts;
        
        // Save updated data
        file_put_contents($cache_file, json_encode($data));
        
        return [
            'limited' => $is_limited,
            'remaining' => max(0, $max_attempts - $attempts_count),
            'reset_time' => $now + $time_window
        ];
    }
    
    /**
     * Log security events
     */
    public static function logSecurityEvent($event_type, $user_id = null, $details = []) {
        $log_entry = [
            'timestamp' => date('Y-m-d H:i:s'),
            'event_type' => $event_type,
            'user_id' => $user_id,
            'ip_address' => $_SERVER['REMOTE_ADDR'] ?? 'unknown',
            'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'unknown',
            'details' => $details
        ];
        
        $log_file = __DIR__ . '/../logs/security.log';
        file_put_contents($log_file, json_encode($log_entry) . PHP_EOL, FILE_APPEND | LOCK_EX);
    }
    
    /**
     * Check if request is from a known bot/crawler
     */
    public static function isBotRequest() {
        $user_agent = $_SERVER['HTTP_USER_AGENT'] ?? '';
        
        $bots = [
            'googlebot', 'bingbot', 'slurp', 'duckduckbot', 'baiduspider',
            'yandexbot', 'sogou', 'exabot', 'facebookexternalhit', 'twitterbot'
        ];
        
        foreach ($bots as $bot) {
            if (stripos($user_agent, $bot) !== false) {
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * Validate and sanitize URL
     */
    public static function sanitizeUrl($url) {
        $url = filter_var($url, FILTER_SANITIZE_URL);
        
        // Validate URL format
        if (!filter_var($url, FILTER_VALIDATE_URL)) {
            return false;
        }
        
        // Restrict to HTTP/HTTPS protocols
        $allowed_protocols = ['http', 'https'];
        $parsed = parse_url($url);
        
        if (!in_array($parsed['scheme'] ?? '', $allowed_protocols)) {
            return false;
        }
        
        return $url;
    }
}

// Initialize security measures
if (defined('ENVIRONMENT') && ENVIRONMENT === 'production') {
    // Set secure session parameters
    ini_set('session.cookie_httponly', 1);
    ini_set('session.cookie_secure', 1);
    ini_set('session.use_strict_mode', 1);
    
    // Hide PHP version
    header_remove('X-Powered-By');
    
    // Set content security policy
    header("Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'");
}