<?php
require_once __DIR__ . '/../config/database.php';
require_once __DIR__ . '/../config/app.php';

// Security functions
function sanitizeInput($data) {
    $data = trim($data);
    $data = stripslashes($data);
    $data = htmlspecialchars($data, ENT_QUOTES, 'UTF-8');
    return $data;
}

function generateCSRFToken() {
    if (!isset($_SESSION['csrf_token'])) {
        $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
    }
    return $_SESSION['csrf_token'];
}

function validateCSRFToken($token) {
    return isset($_SESSION['csrf_token']) && hash_equals($_SESSION['csrf_token'], $token);
}

function generateSecureSessionId() {
    return bin2hex(random_bytes(32));
}

// Validation functions
function validateEmail($email) {
    return filter_var($email, FILTER_VALIDATE_EMAIL);
}

function validatePhone($phone) {
    return preg_match('/^[0-9]{10,15}$/', $phone);
}

function validateNumberPlate($numberPlate) {
    // New format: KA + 2 digits + 1–2 uppercase letters + 4 digits (e.g., KA14A2602 or KA14DC0112)
    return preg_match('/^KA[0-9]{2}[A-Z]{1,2}[0-9]{4}$/', $numberPlate);
}

function validatePassword($password) {
    // SECURITY ENHANCEMENT: Increased minimum length to 16 characters
    if (strlen($password) < 16) return false;
    
    // Require uppercase, lowercase, number, special character
    if (!preg_match('/[A-Z]/', $password)) return false;
    if (!preg_match('/[a-z]/', $password)) return false;
    if (!preg_match('/[0-9]/', $password)) return false;
    if (!preg_match('/[^A-Za-z0-9]/', $password)) return false;
    
    // SECURITY ENHANCEMENT: Check against expanded common password list
    $commonPasswords = [
        'password', '123456', 'qwerty', 'admin', 'password123', '123456789',
        'letmein', 'welcome', 'monkey', 'dragon', 'master', 'football',
        'baseball', 'superman', 'batman', 'trustno1', 'hello', 'shadow',
        'michael', 'jordan', 'harley', 'ranger', 'buster', 'thomas',
        'tigger', 'robert', 'soccer', 'tiger', 'charlie', 'golf',
        'bond007', 'murphy', 'ginger', 'hammer', 'silver', 'golden',
        'fire', 'cookie', 'monster', 'spider', 'cooper', 'carlos',
        'david', 'steven', 'frank', 'dude', 'samson', 'zebra',
        'thx1138', 'matrix', 'coffee', 'scooby', 'froggy', 'orange'
    ];
    if (in_array(strtolower($password), $commonPasswords)) return false;
    
    // SECURITY ENHANCEMENT: Check for sequential characters
    if (preg_match('/(.)\1{2,}/', $password)) return false; // No 3+ repeated characters
    
    // SECURITY ENHANCEMENT: Check for keyboard patterns
    $keyboardPatterns = ['qwerty', 'asdfgh', 'zxcvbn', '123456', '654321'];
    foreach ($keyboardPatterns as $pattern) {
        if (stripos($password, $pattern) !== false) return false;
    }
    
    // SECURITY ENHANCEMENT: Check for common substitutions
    $substitutions = [
        'a' => ['@', '4'], 'e' => ['3'], 'i' => ['1', '!'], 
        'o' => ['0'], 's' => ['$', '5'], 't' => ['7']
    ];
    
    foreach ($substitutions as $letter => $subs) {
        foreach ($subs as $sub) {
            $testPassword = str_replace($sub, $letter, strtolower($password));
            if (in_array($testPassword, $commonPasswords)) return false;
        }
    }
    
    return true;
}

// File upload functions
function validateImageFile($file) {
    $allowedTypes = explode(',', $_ENV['ALLOWED_IMAGE_TYPES']);
    $maxSize = $_ENV['MAX_FILE_SIZE'];
    
    if ($file['error'] !== UPLOAD_ERR_OK) {
        return false;
    }
    
    if ($file['size'] > $maxSize) {
        return false;
    }
    
    // SECURITY ENHANCEMENT: Strict MIME type validation
    $finfo = finfo_open(FILEINFO_MIME_TYPE);
    $mimeType = finfo_file($finfo, $file['tmp_name']);
    finfo_close($finfo);
    
    // SECURITY FIX: Only allow specific image MIME types
    $allowedMimeTypes = [
        'image/jpeg',
        'image/jpg', 
        'image/png',
        'image/gif'
    ];
    
    if (!in_array($mimeType, $allowedMimeTypes)) {
        logError('Invalid MIME type attempted: ' . $mimeType . ' for file: ' . $file['name']);
        return false;
    }
    
    $extension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
    
    // SECURITY ENHANCEMENT: Validate both extension and MIME type match
    $extensionMimeMap = [
        'jpg' => ['image/jpeg', 'image/jpg'],
        'jpeg' => ['image/jpeg', 'image/jpg'],
        'png' => ['image/png'],
        'gif' => ['image/gif']
    ];
    
    if (!isset($extensionMimeMap[$extension]) || !in_array($mimeType, $extensionMimeMap[$extension])) {
        logError('MIME type and extension mismatch: ' . $mimeType . ' vs ' . $extension . ' for file: ' . $file['name']);
        return false;
    }
    
    // SECURITY ENHANCEMENT: Check file header for image signatures
    $fileHandle = fopen($file['tmp_name'], 'rb');
    if ($fileHandle) {
        $header = fread($fileHandle, 8);
        fclose($fileHandle);
        
        $validHeaders = [
            'jpg' => "\xFF\xD8\xFF",
            'jpeg' => "\xFF\xD8\xFF", 
            'png' => "\x89PNG\r\n\x1A\n",
            'gif' => "GIF87a",
            'gif2' => "GIF89a"
        ];
        
        $headerValid = false;
        foreach ($validHeaders as $ext => $signature) {
            if (strpos($header, $signature) === 0) {
                $headerValid = true;
                break;
            }
        }
        
        if (!$headerValid) {
            logError('Invalid file header detected for file: ' . $file['name']);
            return false;
        }
    }
    
    return in_array($extension, $allowedTypes);
}

function uploadFile($file, $directory, $prefix = '') {
    $uploadDir = __DIR__ . '/../uploads/' . $directory . '/';
    
    if (!is_dir($uploadDir)) {
        mkdir($uploadDir, 0755, true);
    }
    
    $extension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
    $filename = $prefix . '_' . uniqid() . '_' . time() . '.' . $extension;
    $filepath = $uploadDir . $filename;
    
    if (move_uploaded_file($file['tmp_name'], $filepath)) {
        return $directory . '/' . $filename;
    }
    
    return false;
}

// QR Code functions
function generateQRCode($data, $filename) {
    try {
        // Check if GD extension is available
        if (!extension_loaded('gd')) {
            // No fallback needed - return false to trigger client-side generation
            return false;
        }
        
        require_once __DIR__ . '/../vendor/autoload.php';
        
        // Create QR code with new v4.x API
        $qrCode = \Endroid\QrCode\QrCode::create(json_encode($data))
            ->setSize(300)
            ->setMargin(10);
        
        // Create PNG writer
        $writer = new \Endroid\QrCode\Writer\PngWriter();
        
        // Generate QR code
        $result = $writer->write($qrCode);
        
        // Ensure uploads directory exists
        $uploadDir = __DIR__ . '/../uploads/qr_codes/';
        if (!is_dir($uploadDir)) {
            mkdir($uploadDir, 0755, true);
        }
        
        // Write file
        $filepath = $uploadDir . $filename . '.png';
        $result->saveToFile($filepath);
        
        return 'qr_codes/' . $filename . '.png';
        
    } catch (Exception $e) {
        logError('QR Code generation error: ' . $e->getMessage());
        return false;
    }
}

// Session management functions
function startSecureSession() {
    if (session_status() === PHP_SESSION_NONE) {
        // SECURITY ENHANCEMENT: Reduced session timeout to 8 hours
        ini_set('session.gc_maxlifetime', 8 * 60 * 60);
        ini_set('session.cookie_lifetime', 8 * 60 * 60);
        ini_set('session.cookie_httponly', 1);
        // Only set secure cookie for HTTPS connections
        if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') {
            ini_set('session.cookie_secure', 1);
        }
        ini_set('session.use_strict_mode', 1);
        // SECURITY ENHANCEMENT: Prevent session fixation
        ini_set('session.use_only_cookies', 1);
        ini_set('session.cookie_samesite', 'Strict');
        session_start();
        
        // SECURITY ENHANCEMENT: Regenerate session ID on first start
        if (!isset($_SESSION['initialized'])) {
            session_regenerate_id(true);
            $_SESSION['initialized'] = true;
            $_SESSION['created_at'] = time();
            $_SESSION['last_activity'] = time();
        }
    }
}

function regenerateSession() {
    session_regenerate_id(true);
}

function destroySession() {
    session_destroy();
    setcookie(session_name(), '', time() - 3600, '/');
}

function checkSessionExpiry() {
    if (!isset($_SESSION['login_time'])) {
        return false;
    }
    
    // SECURITY ENHANCEMENT: Reduced session lifetime to 8 hours
    $sessionLifetime = 8 * 60 * 60; // 8 hours
    
    // SECURITY ENHANCEMENT: Check for idle timeout (30 minutes)
    $idleTimeout = 30 * 60; // 30 minutes
    if (isset($_SESSION['last_activity']) && (time() - $_SESSION['last_activity']) > $idleTimeout) {
        logError('Session expired due to inactivity for user: ' . ($_SESSION['user_id'] ?? 'unknown'));
        destroySession();
        return false;
    }
    
    if (time() - $_SESSION['login_time'] > $sessionLifetime) {
        logError('Session expired due to time limit for user: ' . ($_SESSION['user_id'] ?? 'unknown'));
        destroySession();
        return false;
    }
    
    // SECURITY ENHANCEMENT: Update last activity
    $_SESSION['last_activity'] = time();
    
    return true;
}

function validateDatabaseSession() {
    $db = Database::getInstance();
    $sessionId = session_id();
    
    $session = $db->fetch(
        "SELECT * FROM user_sessions WHERE session_id = ? AND expires_at > NOW()",
        [$sessionId]
    );
    
    if (!$session) {
        destroySession();
        return false;
    }
    
    return true;
}

// User authentication functions
function loginUser($user, $userType) {
    startSecureSession();
    regenerateSession();
    
    $_SESSION['user_id'] = $user['id'];
    $_SESSION['user_type'] = $userType;
    $_SESSION['user_name'] = $user['name'];
    $_SESSION['user_email'] = $user['email'];
    $_SESSION['login_time'] = time();
    
    // Store session in database
    $db = Database::getInstance();
    $sessionId = session_id();
    $ipAddress = $_SERVER['REMOTE_ADDR'] ?? '';
    $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? '';
    $expiresAt = date('Y-m-d H:i:s', time() + (24 * 60 * 60)); // 24 hours
    
    $db->query(
        "INSERT INTO user_sessions (account_id, user_type, session_id, ip_address, user_agent, expires_at) 
         VALUES (?, ?, ?, ?, ?, ?)",
        [$user['id'], $userType, $sessionId, $ipAddress, $userAgent, $expiresAt]
    );
}

function isLoggedIn() {
    startSecureSession();
    
    if (!isset($_SESSION['user_id'])) {
        return false;
    }
    
    // Check both PHP session and database session expiry
    if (!checkSessionExpiry() || !validateDatabaseSession()) {
        return false;
    }
    
    return true;
}

function requireLogin() {
    if (!isLoggedIn()) {
        redirect('/auth/login.php');
    }
}

function requireUserType($userType) {
    requireLogin();
    if ($_SESSION['user_type'] !== $userType) {
        redirect('/dashboard/');
    }
}

function getCurrentUser() {
    if (!isLoggedIn()) {
        return null;
    }
    
    $db = Database::getInstance();
    $accountId = $_SESSION['user_id'];
    $userType = $_SESSION['user_type'] ?? null;

    if ($userType === 'auto_owner') {
        return $db->fetch("SELECT * FROM auto_owners WHERE id = ?", [$accountId]);
    }
    if ($userType === 'passenger') {
        return $db->fetch("SELECT * FROM passengers WHERE id = ?", [$accountId]);
    }
    if ($userType === 'operator') {
        return $db->fetch("SELECT * FROM operators WHERE id = ?", [$accountId]);
    }
    if ($userType === 'validator') {
        return $db->fetch("SELECT * FROM validators WHERE id = ?", [$accountId]);
    }
    if ($userType === 'admin') {
        return $db->fetch("SELECT * FROM admins WHERE id = ?", [$accountId]);
    }
    if ($userType === 'super_admin') {
        return $db->fetch("SELECT * FROM super_admins WHERE id = ?", [$accountId]);
    }

    return null;
}

function getCurrentUserType() {
    startSecureSession();
    return $_SESSION['user_type'] ?? null;
}

// Backend user management functions
function isBackendUser() {
    if (!isLoggedIn()) {
        return false;
    }
    
    $backendTypes = ['operator', 'validator', 'admin', 'super_admin'];
    return in_array($_SESSION['user_type'], $backendTypes);
}

function requireBackendAccess() {
    if (!isBackendUser()) {
        redirect('/auth/login.php');
    }
}

function requireSuperAdminAccess() {
    requireLogin();
    if ($_SESSION['user_type'] !== 'super_admin') {
        redirect('/dashboard/');
    }
}

function isSuperAdmin() {
    startSecureSession();
    return isset($_SESSION['user_type']) && $_SESSION['user_type'] === 'super_admin';
}

function requireAdminAccess() {
    requireLogin();
    $adminTypes = ['admin', 'super_admin'];
    if (!in_array($_SESSION['user_type'], $adminTypes)) {
        redirect('/dashboard/');
    }
}

function requireOperatorAccess() {
    requireLogin();
    $operatorTypes = ['operator', 'validator', 'admin', 'super_admin'];
    if (!in_array($_SESSION['user_type'], $operatorTypes)) {
        redirect('/dashboard/');
    }
}

function requireValidatorAccess() {
    requireLogin();
    $validatorTypes = ['validator', 'admin', 'super_admin'];
    if (!in_array($_SESSION['user_type'], $validatorTypes)) {
        redirect('/dashboard/');
    }
}

// Backend user creation functions (Admin and SuperAdmin can create)
function createBackendUser($userData, $userType, $createdBy) {
    if (!isBackendUser() || !in_array($_SESSION['user_type'], ['admin', 'super_admin'])) {
        return ['success' => false, 'message' => 'Unauthorized access'];
    }
    
    $db = Database::getInstance();
    
    // Validate user type
    $validTypes = ['operator', 'validator', 'admin'];
    if (!in_array($userType, $validTypes)) {
        return ['success' => false, 'message' => 'Invalid user type'];
    }
    
    // Check if email already exists in any user table
    $tables = ['auto_owners', 'passengers', 'operators', 'validators', 'admins', 'super_admins'];
    foreach ($tables as $table) {
        $existingUser = $db->fetch("SELECT id FROM $table WHERE email = ?", [$userData['email']]);
        if ($existingUser) {
            return ['success' => false, 'message' => 'Email already exists in the system'];
        }
    }
    
    try {
        $hashedPassword = password_hash($userData['password'], PASSWORD_DEFAULT);
        
        $sql = "INSERT INTO $userType (name, email, password, phone, status, created_by) VALUES (?, ?, ?, ?, ?, ?)";
        $db->query($sql, [
            $userData['name'],
            $userData['email'],
            $hashedPassword,
            $userData['phone'] ?? '',
            'pending',
            $createdBy
        ]);
        
        return ['success' => true, 'message' => ucfirst($userType) . ' created successfully', 'id' => $db->lastInsertId()];
    } catch (Exception $e) {
        logError('Backend user creation error: ' . $e->getMessage());
        return ['success' => false, 'message' => 'Failed to create user'];
    }
}

function getBackendUsers($userType = null) {
    if (!isBackendUser()) {
        return [];
    }
    
    $db = Database::getInstance();
    
    if ($userType) {
        $validTypes = ['operators', 'validators', 'admins', 'super_admins'];
        if (!in_array($userType, $validTypes)) {
            return [];
        }
        
        try {
            return $db->fetchAll("SELECT * FROM $userType ORDER BY created_at DESC");
        } catch (Exception $e) {
            // Table doesn't exist yet
            return [];
        }
    }
    
    // Return all backend users
    $users = [];
    $tables = ['operators', 'validators', 'admins', 'super_admins'];
    
    // If current user is admin (not super_admin), exclude admin and super_admin tables
    if ($_SESSION['user_type'] === 'admin') {
        $tables = ['operators', 'validators'];
    }
    
    foreach ($tables as $table) {
        try {
            $tableUsers = $db->fetchAll("SELECT *, '$table' as user_table FROM $table ORDER BY created_at DESC");
            $users = array_merge($users, $tableUsers);
        } catch (Exception $e) {
            // Table doesn't exist yet, skip it
            continue;
        }
    }
    
    return $users;
}

// Location management functions
// From Locations (SuperAdmin only)
function createFromLocation($locationData) {
    if (!isBackendUser() || $_SESSION['user_type'] !== 'super_admin') {
        return ['success' => false, 'message' => 'Access denied. Only SuperAdmin can create from locations.'];
    }
    
    $db = Database::getInstance();
    
    try {
        // Validate required fields
        $requiredFields = ['name', 'address', 'city', 'state'];
        foreach ($requiredFields as $field) {
            if (empty($locationData[$field])) {
                return ['success' => false, 'message' => ucfirst($field) . ' is required'];
            }
        }
        
        // Validate coordinates if provided
        if (!empty($locationData['latitude']) && !is_numeric($locationData['latitude'])) {
            return ['success' => false, 'message' => 'Invalid latitude value'];
        }
        if (!empty($locationData['longitude']) && !is_numeric($locationData['longitude'])) {
            return ['success' => false, 'message' => 'Invalid longitude value'];
        }
        
        $sql = "INSERT INTO from_locations (name, address, city, state, pincode, latitude, longitude, description, created_by) 
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
        
        $db->query($sql, [
            $locationData['name'],
            $locationData['address'],
            $locationData['city'],
            $locationData['state'],
            $locationData['pincode'] ?? null,
            $locationData['latitude'] ?? null,
            $locationData['longitude'] ?? null,
            $locationData['description'] ?? null,
            $_SESSION['user_id']
        ]);
        
        $locationId = $db->lastInsertId();
        logError('SuperAdmin created new from location: ' . $locationData['name'] . ' (ID: ' . $locationId . ')');
        
        return ['success' => true, 'message' => 'From location created successfully', 'id' => $locationId];
    } catch (Exception $e) {
        logError('From location creation error: ' . $e->getMessage());
        return ['success' => false, 'message' => 'Failed to create from location'];
    }
}

// To Locations (Admin and SuperAdmin can manage)
function createToLocation($locationData) {
    if (!isBackendUser() || !in_array($_SESSION['user_type'], ['admin', 'super_admin'])) {
        return ['success' => false, 'message' => 'Access denied. Only Admin and SuperAdmin can create to locations.'];
    }
    
    $db = Database::getInstance();
    
    try {
        // Validate required fields
        $requiredFields = ['name', 'address', 'city', 'state'];
        foreach ($requiredFields as $field) {
            if (empty($locationData[$field])) {
                return ['success' => false, 'message' => ucfirst($field) . ' is required'];
            }
        }
        
        // Validate coordinates if provided
        if (!empty($locationData['latitude']) && !is_numeric($locationData['latitude'])) {
            return ['success' => false, 'message' => 'Invalid latitude value'];
        }
        if (!empty($locationData['longitude']) && !is_numeric($locationData['longitude'])) {
            return ['success' => false, 'message' => 'Invalid longitude value'];
        }
        
        $sql = "INSERT INTO to_locations (name, address, city, state, pincode, latitude, longitude, description, created_by) 
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
        
        $db->query($sql, [
            $locationData['name'],
            $locationData['address'],
            $locationData['city'],
            $locationData['state'],
            $locationData['pincode'] ?? null,
            $locationData['latitude'] ?? null,
            $locationData['longitude'] ?? null,
            $locationData['description'] ?? null,
            $_SESSION['user_id']
        ]);
        
        $locationId = $db->lastInsertId();
        logError('User created new to location: ' . $locationData['name'] . ' (ID: ' . $locationId . ')');
        
        return ['success' => true, 'message' => 'To location created successfully', 'id' => $locationId];
    } catch (Exception $e) {
        logError('To location creation error: ' . $e->getMessage());
        return ['success' => false, 'message' => 'Failed to create to location'];
    }
}

// Update functions for both location types
function updateFromLocation($locationId, $locationData) {
    if (!isBackendUser() || $_SESSION['user_type'] !== 'super_admin') {
        return ['success' => false, 'message' => 'Access denied. Only SuperAdmin can update from locations.'];
    }
    
    $db = Database::getInstance();
    
    try {
        // Validate required fields
        $requiredFields = ['name', 'address', 'city', 'state'];
        foreach ($requiredFields as $field) {
            if (empty($locationData[$field])) {
                return ['success' => false, 'message' => ucfirst($field) . ' is required'];
            }
        }
        
        // Validate coordinates if provided
        if (!empty($locationData['latitude']) && !is_numeric($locationData['latitude'])) {
            return ['success' => false, 'message' => 'Invalid latitude value'];
        }
        if (!empty($locationData['longitude']) && !is_numeric($locationData['longitude'])) {
            return ['success' => false, 'message' => 'Invalid longitude value'];
        }
        
        $sql = "UPDATE from_locations SET name = ?, address = ?, city = ?, state = ?, pincode = ?, 
                latitude = ?, longitude = ?, description = ?, updated_at = CURRENT_TIMESTAMP 
                WHERE id = ?";
        
        $db->query($sql, [
            $locationData['name'],
            $locationData['address'],
            $locationData['city'],
            $locationData['state'],
            $locationData['pincode'] ?? null,
            $locationData['latitude'] ?? null,
            $locationData['longitude'] ?? null,
            $locationData['description'] ?? null,
            $locationId
        ]);
        
        logError('SuperAdmin updated from location: ' . $locationData['name'] . ' (ID: ' . $locationId . ')');
        
        return ['success' => true, 'message' => 'From location updated successfully'];
    } catch (Exception $e) {
        logError('From location update error: ' . $e->getMessage());
        return ['success' => false, 'message' => 'Failed to update from location'];
    }
}

function updateToLocation($locationId, $locationData) {
    if (!isBackendUser() || !in_array($_SESSION['user_type'], ['admin', 'super_admin'])) {
        return ['success' => false, 'message' => 'Access denied. Only Admin and SuperAdmin can update to locations.'];
    }
    
    $db = Database::getInstance();
    
    try {
        // Validate required fields
        $requiredFields = ['name', 'address', 'city', 'state'];
        foreach ($requiredFields as $field) {
            if (empty($locationData[$field])) {
                return ['success' => false, 'message' => ucfirst($field) . ' is required'];
            }
        }
        
        // Validate coordinates if provided
        if (!empty($locationData['latitude']) && !is_numeric($locationData['latitude'])) {
            return ['success' => false, 'message' => 'Invalid latitude value'];
        }
        if (!empty($locationData['longitude']) && !is_numeric($locationData['longitude'])) {
            return ['success' => false, 'message' => 'Invalid longitude value'];
        }
        
        $sql = "UPDATE to_locations SET name = ?, address = ?, city = ?, state = ?, pincode = ?, 
                latitude = ?, longitude = ?, description = ?, updated_at = CURRENT_TIMESTAMP 
                WHERE id = ?";
        
        $db->query($sql, [
            $locationData['name'],
            $locationData['address'],
            $locationData['city'],
            $locationData['state'],
            $locationData['pincode'] ?? null,
            $locationData['latitude'] ?? null,
            $locationData['longitude'] ?? null,
            $locationData['description'] ?? null,
            $locationId
        ]);
        
        logError('User updated to location: ' . $locationData['name'] . ' (ID: ' . $locationId . ')');
        
        return ['success' => true, 'message' => 'To location updated successfully'];
    } catch (Exception $e) {
        logError('To location update error: ' . $e->getMessage());
        return ['success' => false, 'message' => 'Failed to update to location'];
    }
}

// Delete functions for both location types
function deleteFromLocation($locationId) {
    if (!isBackendUser() || $_SESSION['user_type'] !== 'super_admin') {
        return ['success' => false, 'message' => 'Access denied. Only SuperAdmin can delete from locations.'];
    }
    
    $db = Database::getInstance();
    
    try {
        // Check if location exists
        $location = $db->fetch("SELECT name FROM from_locations WHERE id = ?", [$locationId]);
        if (!$location) {
            return ['success' => false, 'message' => 'From location not found'];
        }
        
        $db->query("DELETE FROM from_locations WHERE id = ?", [$locationId]);
        
        logError('SuperAdmin deleted from location: ' . $location['name'] . ' (ID: ' . $locationId . ')');
        
        return ['success' => true, 'message' => 'From location deleted successfully'];
    } catch (Exception $e) {
        logError('From location deletion error: ' . $e->getMessage());
        return ['success' => false, 'message' => 'Failed to delete from location'];
    }
}

function deleteToLocation($locationId) {
    if (!isBackendUser() || !in_array($_SESSION['user_type'], ['admin', 'super_admin'])) {
        return ['success' => false, 'message' => 'Access denied. Only Admin and SuperAdmin can delete to locations.'];
    }
    
    $db = Database::getInstance();
    
    try {
        // Check if location exists
        $location = $db->fetch("SELECT name FROM to_locations WHERE id = ?", [$locationId]);
        if (!$location) {
            return ['success' => false, 'message' => 'To location not found'];
        }
        
        $db->query("DELETE FROM to_locations WHERE id = ?", [$locationId]);
        
        logError('User deleted to location: ' . $location['name'] . ' (ID: ' . $locationId . ')');
        
        return ['success' => true, 'message' => 'To location deleted successfully'];
    } catch (Exception $e) {
        logError('To location deletion error: ' . $e->getMessage());
        return ['success' => false, 'message' => 'Failed to delete to location'];
    }
}

// Get functions for both location types
function getFromLocations($status = null) {
    if (!isBackendUser()) {
        return [];
    }
    
    $db = Database::getInstance();
    
    try {
        if ($status) {
            return $db->fetchAll("SELECT * FROM from_locations WHERE status = ? ORDER BY name ASC", [$status]);
        }
        
        return $db->fetchAll("SELECT * FROM from_locations ORDER BY name ASC");
    } catch (Exception $e) {
        // Table might not exist yet, return empty array
        logError('Error getting from locations: ' . $e->getMessage());
        return [];
    }
}

function getToLocations($status = null) {
    if (!isBackendUser()) {
        return [];
    }
    
    $db = Database::getInstance();
    
    try {
        if ($status) {
            return $db->fetchAll("SELECT * FROM to_locations WHERE status = ? ORDER BY name ASC", [$status]);
        }
        
        return $db->fetchAll("SELECT * FROM to_locations ORDER BY name ASC");
    } catch (Exception $e) {
        // Table might not exist yet, return empty array
        logError('Error getting to locations: ' . $e->getMessage());
        return [];
    }
}

// Get individual location functions
function getFromLocationById($locationId) {
    if (!isBackendUser()) {
        return null;
    }
    
    $db = Database::getInstance();
    return $db->fetch("SELECT * FROM from_locations WHERE id = ?", [$locationId]);
}

function getToLocationById($locationId) {
    if (!isBackendUser()) {
        return null;
    }
    
    $db = Database::getInstance();
    return $db->fetch("SELECT * FROM to_locations WHERE id = ?", [$locationId]);
}

// Toggle status functions for both location types
function toggleFromLocationStatus($locationId) {
    if (!isBackendUser() || $_SESSION['user_type'] !== 'super_admin') {
        return ['success' => false, 'message' => 'Access denied. Only SuperAdmin can change from location status.'];
    }
    
    $db = Database::getInstance();
    
    try {
        $location = $db->fetch("SELECT name, status FROM from_locations WHERE id = ?", [$locationId]);
        if (!$location) {
            return ['success' => false, 'message' => 'From location not found'];
        }
        
        $newStatus = $location['status'] === 'active' ? 'inactive' : 'active';
        $db->query("UPDATE from_locations SET status = ? WHERE id = ?", [$newStatus, $locationId]);
        
        logError('SuperAdmin changed from location status: ' . $location['name'] . ' to ' . $newStatus . ' (ID: ' . $locationId . ')');
        
        return ['success' => true, 'message' => 'From location status updated successfully', 'new_status' => $newStatus];
    } catch (Exception $e) {
        logError('From location status update error: ' . $e->getMessage());
        return ['success' => false, 'message' => 'Failed to update from location status'];
    }
}

function toggleToLocationStatus($locationId) {
    if (!isBackendUser() || !in_array($_SESSION['user_type'], ['admin', 'super_admin'])) {
        return ['success' => false, 'message' => 'Access denied. Only Admin and SuperAdmin can change to location status.'];
    }
    
    $db = Database::getInstance();
    
    try {
        $location = $db->fetch("SELECT name, status FROM to_locations WHERE id = ?", [$locationId]);
        if (!$location) {
            return ['success' => false, 'message' => 'To location not found'];
        }
        
        $newStatus = $location['status'] === 'active' ? 'inactive' : 'active';
        $db->query("UPDATE to_locations SET status = ? WHERE id = ?", [$newStatus, $locationId]);
        
        logError('User changed to location status: ' . $location['name'] . ' to ' . $newStatus . ' (ID: ' . $locationId . ')');
        
        return ['success' => true, 'message' => 'To location status updated successfully', 'new_status' => $newStatus];
    } catch (Exception $e) {
        logError('To location status update error: ' . $e->getMessage());
        return ['success' => false, 'message' => 'Failed to update to location status'];
    }
}

// Auto Rickshaw Management Functions (Admin/Validator access)
function getAutoRickshaws($status = null, $limit = null) {
    if (!isBackendUser()) {
        return [];
    }
    
    try {
        $db = Database::getInstance();
        $pdo = $db->getConnection();
        
        // Check if auto_rickshaws table exists
        $result = $pdo->query("SHOW TABLES LIKE 'auto_rickshaws'");
        if ($result->rowCount() === 0) {
            logError('Auto rickshaws table does not exist');
            return [];
        }
        
        // Check if auto_owners table exists
        $result = $pdo->query("SHOW TABLES LIKE 'auto_owners'");
        if ($result->rowCount() === 0) {
            logError('Auto owners table does not exist');
            return [];
        }
        
        $sql = "SELECT ar.*, ao.name as owner_name, ao.email as owner_email, ao.phone as owner_phone 
                FROM auto_rickshaws ar 
                JOIN auto_owners ao ON ar.owner_id = ao.id";
        
        $params = [];
        if ($status) {
            $sql .= " WHERE ar.status = ?";
            $params[] = $status;
        }
        
        $sql .= " ORDER BY ar.created_at DESC";
        
        if ($limit) {
            $sql .= " LIMIT ?";
            $params[] = $limit;
        }
        
        return $db->fetchAll($sql, $params);
    } catch (Exception $e) {
        logError('Error fetching auto rickshaws: ' . $e->getMessage());
        return [];
    }
}

function getAutoRickshawById($id) {
    if (!isBackendUser()) {
        return null;
    }
    
    $db = Database::getInstance();
    
    $sql = "SELECT ar.*, ao.name as owner_name, ao.email as owner_email, ao.phone as owner_phone 
            FROM auto_rickshaws ar 
            JOIN auto_owners ao ON ar.owner_id = ao.id 
            WHERE ar.id = ?";
    
    try {
        return $db->fetch($sql, [$id]);
    } catch (Exception $e) {
        logError('Error fetching auto rickshaw: ' . $e->getMessage());
        return null;
    }
}

function updateAutoRickshawStatus($id, $status, $adminId) {
    if (!isBackendUser() || !in_array($_SESSION['user_type'], ['admin', 'super_admin', 'validator'])) {
        return ['success' => false, 'message' => 'Access denied'];
    }
    
    $validStatuses = ['active', 'inactive', 'pending_approval'];
    if (!in_array($status, $validStatuses)) {
        return ['success' => false, 'message' => 'Invalid status'];
    }
    
    $db = Database::getInstance();
    
    try {
        $rickshaw = $db->fetch("SELECT * FROM auto_rickshaws WHERE id = ?", [$id]);
        if (!$rickshaw) {
            return ['success' => false, 'message' => 'Auto rickshaw not found'];
        }
        
        $db->query("UPDATE auto_rickshaws SET status = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?", [$status, $id]);
        
        logError('Admin updated auto rickshaw status: ID ' . $id . ' to ' . $status . ' by admin ID ' . $adminId);
        
        return ['success' => true, 'message' => 'Auto rickshaw status updated successfully'];
    } catch (Exception $e) {
        logError('Error updating auto rickshaw status: ' . $e->getMessage());
        return ['success' => false, 'message' => 'Failed to update status'];
    }
}

// Fare Management Functions (Admin access)
function getFareDetails($status = null) {
    if (!isBackendUser() || !in_array($_SESSION['user_type'], ['admin', 'super_admin'])) {
        return [];
    }
    
    $db = Database::getInstance();
    
    $sql = "SELECT fd.*, 
            fl.name as from_location_name, fl.city as from_city, fl.state as from_state,
            tl.name as to_location_name, tl.city as to_city, tl.state as to_state,
            a.name as created_by_name
            FROM fare_details fd
            JOIN from_locations fl ON fd.from_location_id = fl.id
            JOIN to_locations tl ON fd.to_location_id = tl.id
            JOIN admins a ON fd.created_by = a.id";
    
    $params = [];
    if ($status) {
        $sql .= " WHERE fd.status = ?";
        $params[] = $status;
    }
    
    $sql .= " ORDER BY fl.name, tl.name";
    
    try {
        return $db->fetchAll($sql, $params);
    } catch (Exception $e) {
        logError('Error fetching fare details: ' . $e->getMessage());
        return [];
    }
}

function getFareDetailById($id) {
    if (!isBackendUser() || !in_array($_SESSION['user_type'], ['admin', 'super_admin'])) {
        return null;
    }
    
    $db = Database::getInstance();
    
    $sql = "SELECT fd.*, 
            fl.name as from_location_name, fl.city as from_city, fl.state as from_state,
            tl.name as to_location_name, tl.city as to_city, tl.state as to_state,
            a.name as created_by_name
            FROM fare_details fd
            JOIN from_locations fl ON fd.from_location_id = fl.id
            JOIN to_locations tl ON fd.to_location_id = tl.id
            JOIN admins a ON fd.created_by = a.id
            WHERE fd.id = ?";
    
    try {
        return $db->fetch($sql, [$id]);
    } catch (Exception $e) {
        logError('Error fetching fare detail: ' . $e->getMessage());
        return null;
    }
}

function createFareDetail($fareData, $adminId) {
    if (!isBackendUser() || !in_array($_SESSION['user_type'], ['admin', 'super_admin'])) {
        return ['success' => false, 'message' => 'Access denied'];
    }
    
    $db = Database::getInstance();
    
    // Check if at least one fare type is provided
    $hasFare = !empty($fareData['fix_rate']) || 
                (!empty($fareData['base_fare']) && !empty($fareData['per_km_rate']) && !empty($fareData['minimum_fare']));
    
    if (!$hasFare) {
        return ['success' => false, 'message' => 'Please provide either a Fix Rate or all three: Base Fare, Per KM Rate, and Minimum Fare'];
    }
    
    // Check if route already exists
    $existing = $db->fetch("SELECT id FROM fare_details WHERE from_location_id = ? AND to_location_id = ?", 
                           [$fareData['from_location_id'], $fareData['to_location_id']]);
    if ($existing) {
        return ['success' => false, 'message' => 'Fare for this route already exists'];
    }
    
    try {
        $sql = "INSERT INTO fare_details (from_location_id, to_location_id, base_fare, per_km_rate, minimum_fare, 
                fix_rate, distance_km, estimated_duration_minutes, created_by) 
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
        
        $db->query($sql, [
            $fareData['from_location_id'],
            $fareData['to_location_id'],
            $fareData['base_fare'] ?? null,
            $fareData['per_km_rate'] ?? null,
            $fareData['minimum_fare'] ?? null,
            $fareData['fix_rate'] ?? null,
            $fareData['distance_km'] ?? null,
            $fareData['estimated_duration_minutes'] ?? null,
            $adminId
        ]);
        
        logError('Admin created fare detail: Route ' . $fareData['from_location_id'] . ' to ' . $fareData['to_location_id'] . ' by admin ID ' . $adminId);
        
        return ['success' => true, 'message' => 'Fare detail created successfully', 'id' => $db->lastInsertId()];
    } catch (Exception $e) {
        logError('Error creating fare detail: ' . $e->getMessage());
        return ['success' => false, 'message' => 'Failed to create fare detail'];
    }
}

function updateFareDetail($id, $fareData, $adminId) {
    if (!isBackendUser() || !in_array($_SESSION['user_type'], ['admin', 'super_admin'])) {
        return ['success' => false, 'message' => 'Access denied'];
    }
    
    $db = Database::getInstance();
    
    try {
        $existing = $db->fetch("SELECT * FROM fare_details WHERE id = ?", [$id]);
        if (!$existing) {
            return ['success' => false, 'message' => 'Fare detail not found'];
        }
        
        // Check if route already exists for different ID
        if (isset($fareData['from_location_id']) && isset($fareData['to_location_id'])) {
            $duplicate = $db->fetch("SELECT id FROM fare_details WHERE from_location_id = ? AND to_location_id = ? AND id != ?", 
                                   [$fareData['from_location_id'], $fareData['to_location_id'], $id]);
            if ($duplicate) {
                return ['success' => false, 'message' => 'Fare for this route already exists'];
            }
        }
        
        // Check if at least one fare type is provided
        $hasFare = !empty($fareData['fix_rate']) || 
                    (!empty($fareData['base_fare']) && !empty($fareData['per_km_rate']) && !empty($fareData['minimum_fare']));
        
        if (!$hasFare) {
            return ['success' => false, 'message' => 'Please provide either a Fix Rate or all three: Base Fare, Per KM Rate, and Minimum Fare'];
        }
        
        $sql = "UPDATE fare_details SET 
                from_location_id = ?, to_location_id = ?, base_fare = ?, per_km_rate = ?, 
                minimum_fare = ?, fix_rate = ?, distance_km = ?, estimated_duration_minutes = ?, 
                updated_at = CURRENT_TIMESTAMP 
                WHERE id = ?";
        
        $db->query($sql, [
            $fareData['from_location_id'] ?? $existing['from_location_id'],
            $fareData['to_location_id'] ?? $existing['to_location_id'],
            $fareData['base_fare'] ?? $existing['base_fare'],
            $fareData['per_km_rate'] ?? $existing['per_km_rate'],
            $fareData['minimum_fare'] ?? $existing['minimum_fare'],
            $fareData['fix_rate'] ?? $existing['fix_rate'],
            $fareData['distance_km'] ?? $existing['distance_km'],
            $fareData['estimated_duration_minutes'] ?? $existing['estimated_duration_minutes'],
            $id
        ]);
        
        logError('Admin updated fare detail: ID ' . $id . ' by admin ID ' . $adminId);
        
        return ['success' => true, 'message' => 'Fare detail updated successfully'];
    } catch (Exception $e) {
        logError('Error updating fare detail: ' . $e->getMessage());
        return ['success' => false, 'message' => 'Failed to update fare detail'];
    }
}

function deleteFareDetail($id, $adminId) {
    if (!isBackendUser() || !in_array($_SESSION['user_type'], ['admin', 'super_admin'])) {
        return ['success' => false, 'message' => 'Access denied'];
    }
    
    $db = Database::getInstance();
    
    try {
        $existing = $db->fetch("SELECT * FROM fare_details WHERE id = ?", [$id]);
        if (!$existing) {
            return ['success' => false, 'message' => 'Fare detail not found'];
        }
        
        $db->query("DELETE FROM fare_details WHERE id = ?", [$id]);
        
        logError('Admin deleted fare detail: ID ' . $id . ' by admin ID ' . $adminId);
        
        return ['success' => true, 'message' => 'Fare detail deleted successfully'];
    } catch (Exception $e) {
        logError('Error deleting fare detail: ' . $e->getMessage());
        return ['success' => false, 'message' => 'Failed to delete fare detail'];
    }
}

function toggleFareDetailStatus($id, $adminId) {
    if (!isBackendUser() || !in_array($_SESSION['user_type'], ['admin', 'super_admin'])) {
        return ['success' => false, 'message' => 'Access denied'];
    }
    
    $db = Database::getInstance();
    
    try {
        $fare = $db->fetch("SELECT * FROM fare_details WHERE id = ?", [$id]);
        if (!$fare) {
            return ['success' => false, 'message' => 'Fare detail not found'];
        }
        
        $newStatus = $fare['status'] === 'active' ? 'inactive' : 'active';
        $db->query("UPDATE fare_details SET status = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?", [$newStatus, $id]);
        
        logError('Admin toggled fare detail status: ID ' . $id . ' to ' . $newStatus . ' by admin ID ' . $adminId);
        
        return ['success' => true, 'message' => 'Fare detail status updated successfully', 'new_status' => $newStatus];
    } catch (Exception $e) {
        logError('Error toggling fare detail status: ' . $e->getMessage());
        return ['success' => false, 'message' => 'Failed to update status'];
    }
}

// Legacy function for backward compatibility
function getLocations($status = null) {
    // Return from locations for backward compatibility
    return getFromLocations($status);
}

function getLocationById($locationId) {
    if (!isBackendUser()) {
        return null;
    }
    
    $db = Database::getInstance();
    return $db->fetch("SELECT * FROM locations WHERE id = ?", [$locationId]);
}

function toggleLocationStatus($locationId) {
    if (!isBackendUser() || $_SESSION['user_type'] !== 'super_admin') {
        return ['success' => false, 'message' => 'Access denied. Only SuperAdmin can change location status.'];
    }
    
    $db = Database::getInstance();
    
    try {
        $location = $db->fetch("SELECT name, status FROM locations WHERE id = ?", [$locationId]);
        if (!$location) {
            return ['success' => false, 'message' => 'Location not found'];
        }
        
        $newStatus = $location['status'] === 'active' ? 'inactive' : 'active';
        $db->query("UPDATE locations SET status = ? WHERE id = ?", [$newStatus, $locationId]);
        
        logError('SuperAdmin changed location status: ' . $location['name'] . ' to ' . $newStatus . ' (ID: ' . $locationId . ')');
        
        return ['success' => true, 'message' => 'Location status updated successfully', 'new_status' => $newStatus];
    } catch (Exception $e) {
        logError('Location status update error: ' . $e->getMessage());
        return ['success' => false, 'message' => 'Failed to update location status'];
    }
}

// Response functions
function jsonResponse($data, $statusCode = 200) {
    http_response_code($statusCode);
    header('Content-Type: application/json');
    echo json_encode($data);
    exit();
}

function redirect($url) {
    if (!preg_match('#^https?://#i', $url)) {
        $url = url_for($url);
    }
    header('Location: ' . $url);
    exit();
}

// Error handling functions
function logError($message, $context = []) {
    $logMessage = date('Y-m-d H:i:s') . ' - ' . $message;
    if (!empty($context)) {
        $logMessage .= ' - Context: ' . json_encode($context);
    }
    error_log($logMessage);
}

// Utility functions
function formatDate($date) {
    return date('M d, Y H:i', strtotime($date));
}

function formatCurrency($amount) {
    return '₹' . number_format($amount, 2);
}

function getStatusBadge($status) {
    $badges = [
        'active' => 'success',
        'inactive' => 'danger',
        'pending' => 'warning',
        'pending_approval' => 'warning'
    ];
    
    $badgeClass = $badges[$status] ?? 'secondary';
    return '<span class="badge bg-' . $badgeClass . '">' . ucfirst(str_replace('_', ' ', $status)) . '</span>';
}

// Utility for building URLs relative to the application base path
function url_for($path = '') {
    $base = rtrim(APP_BASE_PATH ?? '', '/');
    $path = '/' . ltrim($path, '/');
    return $base . $path;
}

// Initialize database on first load
if (!function_exists('initializeDatabase')) {
    require_once __DIR__ . '/../config/database.php';
}

// Commission functions
function getCommissionConfig() {
    $db = Database::getInstance();
    $config = $db->fetch("SELECT * FROM commission_config WHERE is_active = 1 ORDER BY id DESC LIMIT 1");
    
    if (!$config) {
        // Return default configuration if none exists
        return [
            'commission_type' => 'percentage',
            'commission_value' => 10.00,
            'min_commission' => null,
            'max_commission' => null
        ];
    }
    
    return $config;
}

function calculateCommission($baseFare) {
    $config = getCommissionConfig();
    
    if ($config['commission_type'] === 'percentage') {
        $commission = $baseFare * ($config['commission_value'] / 100);
        
        // Apply min/max constraints if set
        if ($config['min_commission'] !== null && $commission < $config['min_commission']) {
            $commission = $config['min_commission'];
        }
        if ($config['max_commission'] !== null && $commission > $config['max_commission']) {
            $commission = $config['max_commission'];
        }
        
        return $commission;
    } else {
        // Fixed commission amount
        return $config['commission_value'];
    }
}

function updateCommissionConfig($commissionType, $commissionValue, $minCommission = null, $maxCommission = null, $description = '') {
    if (!isSuperAdmin()) {
        return ['success' => false, 'message' => 'Access denied. Only SuperAdmin can update commission configuration.'];
    }
    
    $db = Database::getInstance();
    
    try {
        // Deactivate current active config
        $db->query("UPDATE commission_config SET is_active = 0 WHERE is_active = 1");
        
        // Insert new configuration
        $sql = "INSERT INTO commission_config (commission_type, commission_value, min_commission, max_commission, description, created_by) VALUES (?, ?, ?, ?, ?, ?)";
        $db->query($sql, [$commissionType, $commissionValue, $minCommission, $maxCommission, $description, $_SESSION['user_id']]);
        
        logError('SuperAdmin updated commission configuration: ' . $commissionType . ' = ' . $commissionValue);
        
        return ['success' => true, 'message' => 'Commission configuration updated successfully'];
    } catch (Exception $e) {
        logError('Commission configuration update error: ' . $e->getMessage());
        return ['success' => false, 'message' => 'Failed to update commission configuration'];
    }
}

function getCommissionHistory() {
    if (!isSuperAdmin()) {
        return [];
    }
    
    $db = Database::getInstance();
    return $db->fetchAll("SELECT * FROM commission_config ORDER BY created_at DESC");
}

function getBackendUserById($userId) {
    if (!$userId) {
        return null;
    }
    
    $db = Database::getInstance();
    
    // Check in all backend user tables, but prioritize super_admins first
    // since commission configurations are only created by SuperAdmins
    $tables = ['super_admins', 'admins', 'validators', 'operators'];
    
    foreach ($tables as $table) {
        try {
            $user = $db->fetch("SELECT * FROM $table WHERE id = ?", [$userId]);
            if ($user) {
                return $user;
            }
        } catch (Exception $e) {
            // Table might not exist yet, continue to next table
            continue;
        }
    }
    
    return null;
} 

function enforceSessionSecurity() {
    // Check session age
    if (isset($_SESSION['login_time']) && (time() - $_SESSION['login_time']) > 3600) {
        destroySession();
        redirect('/auth/login.php?expired=1');
    }
    
    // Validate session against database
    if (!validateDatabaseSession()) {
        destroySession();
        redirect('/auth/login.php?invalid=1');
    }
    
    // Regenerate session ID periodically
    if (isset($_SESSION['last_regeneration']) && (time() - $_SESSION['last_regeneration']) > 1800) {
        regenerateSession();
        $_SESSION['last_regeneration'] = time();
    }
} 

function checkRateLimit($action, $maxAttempts = 5, $timeWindow = 300) {
    $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
    $key = "rate_limit:{$action}:{$ip}";
    
    $attempts = getRateLimitAttempts($key);
    if ($attempts >= $maxAttempts) {
        logError('Rate limit exceeded for action: ' . $action . ' from IP: ' . $ip);
        return false; // Rate limit exceeded
    }
    
    incrementRateLimit($key, $timeWindow);
    return true;
} 

function getRateLimitAttempts($key) {
    // Simple in-memory rate limiting (in production, use Redis or database)
    if (!isset($_SESSION['rate_limits'])) {
        $_SESSION['rate_limits'] = [];
    }
    
    if (!isset($_SESSION['rate_limits'][$key])) {
        return 0;
    }
    
    $data = $_SESSION['rate_limits'][$key];
    if (time() - $data['timestamp'] > $data['window']) {
        return 0; // Window expired
    }
    
    return $data['attempts'];
}

function incrementRateLimit($key, $timeWindow) {
    if (!isset($_SESSION['rate_limits'])) {
        $_SESSION['rate_limits'] = [];
    }
    
    $_SESSION['rate_limits'][$key] = [
        'attempts' => ($_SESSION['rate_limits'][$key]['attempts'] ?? 0) + 1,
        'timestamp' => time(),
        'window' => $timeWindow
    ];
} 

// SECURITY ENHANCEMENT: Enhanced rate limiting for authentication
function checkAuthRateLimit($action, $maxAttempts = 3, $timeWindow = 900) {
    $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
    $key = "auth_rate_limit:{$action}:{$ip}";
    
    $attempts = getRateLimitAttempts($key);
    if ($attempts >= $maxAttempts) {
        logError('Authentication rate limit exceeded for action: ' . $action . ' from IP: ' . $ip);
        return false;
    }
    
    incrementRateLimit($key, $timeWindow);
    return true;
}

// SECURITY ENHANCEMENT: Check for suspicious activity
function checkSuspiciousActivity($userId, $action) {
    $key = "suspicious:{$userId}:{$action}";
    $attempts = getRateLimitAttempts($key);
    
    if ($attempts > 10) {
        logError('Suspicious activity detected for user: ' . $userId . ' action: ' . $action);
        return false;
    }
    
    incrementRateLimit($key, 3600); // 1 hour window
    return true;
}