<?php
/**
 * RUHONDO BEACH RESORT HMS + POS System
 * Authentication and Authorization Functions - FIXED VERSION
 * Developer: JOACHIM'S INNOTECH
 */

// Prevent direct access
if (!defined('BASE_PATH') && !defined('ALLOW_DIRECT_ACCESS')) {
    // Try to define BASE_PATH if not defined
    if (!defined('BASE_PATH')) {
        define('BASE_PATH', dirname(__DIR__));
    }
}

// Ensure session is started
if (session_status() === PHP_SESSION_NONE) {
    session_start();
}

// Helper function to detect if we're in public directory
if (!function_exists('is_in_public_dir')) {
    function is_in_public_dir() {
        $script_name = $_SERVER['SCRIPT_NAME'] ?? '';
        return (strpos($script_name, '/public/') !== false);
    }
}

// Helper function to get correct path
if (!function_exists('get_correct_path')) {
    function get_correct_path($path) {
        $in_public = is_in_public_dir();
        
        // If path already has public/ prefix
        if (strpos($path, 'public/') === 0) {
            return $in_public ? substr($path, 7) : $path;
        }
        
        // If we're in public directory, don't add public/ prefix
        if ($in_public) {
            return $path;
        }
        
        // If we're in root and path doesn't have public/, add it
        return 'public/' . $path;
    }
}

// Define audit constants if not defined
if (!defined('AUDIT_LOGIN_FAILED')) define('AUDIT_LOGIN_FAILED', 'login_failed');
if (!defined('AUDIT_LOGIN')) define('AUDIT_LOGIN', 'login');
if (!defined('AUDIT_LOGOUT')) define('AUDIT_LOGOUT', 'logout');
if (!defined('NOTIFICATION_INFO')) define('NOTIFICATION_INFO', 'info');

// Define a fallback audit_log function if it doesn't exist
if (!function_exists('audit_log')) {
    function audit_log($user_id, $action, $table_name = null, $record_id = null, $old_values = null, $new_values = null) {
        // Simple fallback - log to error log
        $message = "AUDIT: User: $user_id | Action: $action";
        if ($table_name) $message .= " | Table: $table_name";
        if ($record_id) $message .= " | Record: $record_id";
        error_log($message);
        
        // Try to write to audit log file
        $log_file = defined('LOG_AUDIT') ? LOG_AUDIT : dirname(__DIR__) . '/logs/audit.log';
        $timestamp = date('Y-m-d H:i:s');
        $log_entry = "[$timestamp] $message" . PHP_EOL;
        
        $log_dir = dirname($log_file);
        if (!is_dir($log_dir)) {
            @mkdir($log_dir, 0777, true);
        }
        
        @file_put_contents($log_file, $log_entry, FILE_APPEND | LOCK_EX);
    }
}

// Define fallback for create_notification
if (!function_exists('create_notification')) {
    function create_notification($user_id, $type, $title, $message, $link = null) {
        // Simple fallback - just log it
        error_log("NOTIFICATION: User $user_id - $title: $message");
        return true;
    }
}

// Define fallback for get_client_ip
if (!function_exists('get_client_ip')) {
    function get_client_ip() {
        $ipaddress = '';
        if (isset($_SERVER['HTTP_CLIENT_IP'])) {
            $ipaddress = $_SERVER['HTTP_CLIENT_IP'];
        } elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            $ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
        } elseif (isset($_SERVER['HTTP_X_FORWARDED'])) {
            $ipaddress = $_SERVER['HTTP_X_FORWARDED'];
        } elseif (isset($_SERVER['HTTP_FORWARDED_FOR'])) {
            $ipaddress = $_SERVER['HTTP_FORWARDED_FOR'];
        } elseif (isset($_SERVER['HTTP_FORWARDED'])) {
            $ipaddress = $_SERVER['HTTP_FORWARDED'];
        } elseif (isset($_SERVER['REMOTE_ADDR'])) {
            $ipaddress = $_SERVER['REMOTE_ADDR'];
        } else {
            $ipaddress = 'UNKNOWN';
        }
        return $ipaddress;
    }
}

// Define fallback for get_user_agent
if (!function_exists('get_user_agent')) {
    function get_user_agent() {
        return $_SERVER['HTTP_USER_AGENT'] ?? 'UNKNOWN';
    }
}

// Define fallback for log_message
if (!function_exists('log_message')) {
    function log_message($message, $level = 'INFO') {
        error_log("[$level] $message");
    }
}

// Define fallback for set_flash_message
if (!function_exists('set_flash_message')) {
    function set_flash_message($type, $message) {
        if (!isset($_SESSION['flash_messages'])) {
            $_SESSION['flash_messages'] = [];
        }
        $_SESSION['flash_messages'][] = [
            'type' => $type,
            'message' => $message,
            'time' => time()
        ];
    }
}

// Define fallback for display_flash_messages
if (!function_exists('display_flash_messages')) {
    function display_flash_messages() {
        if (isset($_SESSION['flash_messages']) && !empty($_SESSION['flash_messages'])) {
            foreach ($_SESSION['flash_messages'] as $flash) {
                $type = $flash['type'] ?? 'info';
                $message = $flash['message'] ?? '';
                echo '<div class="alert alert-' . htmlspecialchars($type) . ' alert-dismissible fade show" role="alert">';
                echo htmlspecialchars($message);
                echo '<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>';
                echo '</div>';
            }
            $_SESSION['flash_messages'] = [];
        }
    }
}

// Define fallback for redirect_back
if (!function_exists('redirect_back')) {
    function redirect_back($fallback = 'dashboard.php') {
        $referer = $_SERVER['HTTP_REFERER'] ?? '';
        if (!empty($referer)) {
            header('Location: ' . $referer);
        } else {
            redirect($fallback);
        }
        exit;
    }
}

// Define fallback for is_ajax_request
if (!function_exists('is_ajax_request')) {
    function is_ajax_request() {
        return !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && 
               strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
    }
}

// Define fallback for json_error
if (!function_exists('json_error')) {
    function json_error($message, $errors = null, $status_code = 400) {
        http_response_code($status_code);
        header('Content-Type: application/json');
        $response = ['status' => 'error', 'message' => $message];
        if ($errors) $response['errors'] = $errors;
        echo json_encode($response);
        exit;
    }
}

// Define fallback for json_success
if (!function_exists('json_success')) {
    function json_success($data = null, $message = 'Success', $status_code = 200) {
        http_response_code($status_code);
        header('Content-Type: application/json');
        echo json_encode([
            'status' => 'success',
            'message' => $message,
            'data' => $data
        ]);
        exit;
    }
}

// Define improved redirect function
if (!function_exists('redirect')) {
    function redirect($url) {
        // Handle absolute URLs
        if (strpos($url, 'http://') === 0 || strpos($url, 'https://') === 0) {
            header('Location: ' . $url);
            exit;
        }
        
        // Get base URL if defined
        $base = defined('BASE_URL') ? rtrim(BASE_URL, '/') : '';
        
        // Determine correct path
        $correct_path = get_correct_path($url);
        
        // Build full URL
        if (!empty($base)) {
            $full_url = $base . '/' . ltrim($correct_path, '/');
        } else {
            $full_url = $correct_path;
        }
        
        // Remove double slashes
        $full_url = preg_replace('#([^:])//+#', '$1/', $full_url);
        
        error_log("Redirecting to: " . $full_url);
        header('Location: ' . $full_url);
        exit;
    }
}

// =============================================
// USER STATE FUNCTIONS - DEFINED EARLY
// =============================================

/**
 * Check if user is logged in - DEFINED EARLY to avoid undefined function errors
 */
if (!function_exists('is_logged_in')) {
    function is_logged_in() {
        $is_logged = isset($_SESSION['user_id']) && !empty($_SESSION['user_id']) && isset($_SESSION['authenticated']);
        return $is_logged;
    }
}

/**
 * Get current user ID
 */
if (!function_exists('current_user_id')) {
    function current_user_id() {
        return $_SESSION['user_id'] ?? null;
    }
}

/**
 * Get current user role
 */
if (!function_exists('current_user_role')) {
    function current_user_role() {
        return $_SESSION['user_role'] ?? null;
    }
}

// =============================================
// LOGIN ATTEMPT TRACKING
// =============================================

/**
 * Check login attempts for rate limiting
 * 
 * @param string $username
 * @return bool True if allowed, false if locked out
 */
if (!function_exists('check_login_attempts')) {
    function check_login_attempts($username) {
        if (!defined('ENABLE_RATE_LIMITING') || !ENABLE_RATE_LIMITING) {
            return true;
        }
        
        $ip = get_client_ip();
        $key = 'login_attempts_' . md5($ip . '_' . $username);
        
        if (!isset($_SESSION[$key])) {
            $_SESSION[$key] = [
                'count' => 1,
                'first_attempt' => time()
            ];
            return true;
        }
        
        $attempts = $_SESSION[$key];
        $lockout_time = defined('LOGIN_LOCKOUT_TIME') ? LOGIN_LOCKOUT_TIME : 900;
        
        // Reset if lockout period has passed
        if (time() - $attempts['first_attempt'] > $lockout_time) {
            $_SESSION[$key] = [
                'count' => 1,
                'first_attempt' => time()
            ];
            return true;
        }
        
        $max_attempts = defined('MAX_LOGIN_ATTEMPTS') ? MAX_LOGIN_ATTEMPTS : 5;
        
        // Check if exceeded max attempts
        if ($attempts['count'] >= $max_attempts) {
            return false;
        }
        
        // Increment attempts
        $_SESSION[$key]['count']++;
        return true;
    }
}

/**
 * Reset login attempts on successful login
 * 
 * @param string $username
 */
if (!function_exists('reset_login_attempts')) {
    function reset_login_attempts($username) {
        $ip = get_client_ip();
        $key = 'login_attempts_' . md5($ip . '_' . $username);
        unset($_SESSION[$key]);
    }
}

/**
 * Get remaining login attempts
 * 
 * @param string $username
 * @return int Remaining attempts
 */
if (!function_exists('get_remaining_login_attempts')) {
    function get_remaining_login_attempts($username) {
        if (!defined('ENABLE_RATE_LIMITING') || !ENABLE_RATE_LIMITING) {
            return defined('MAX_LOGIN_ATTEMPTS') ? MAX_LOGIN_ATTEMPTS : 5;
        }
        
        $ip = get_client_ip();
        $key = 'login_attempts_' . md5($ip . '_' . $username);
        
        if (!isset($_SESSION[$key])) {
            return defined('MAX_LOGIN_ATTEMPTS') ? MAX_LOGIN_ATTEMPTS : 5;
        }
        
        $attempts = $_SESSION[$key];
        $max_attempts = defined('MAX_LOGIN_ATTEMPTS') ? MAX_LOGIN_ATTEMPTS : 5;
        $lockout_time = defined('LOGIN_LOCKOUT_TIME') ? LOGIN_LOCKOUT_TIME : 900;
        
        // Check if lockout period has passed
        if (time() - $attempts['first_attempt'] > $lockout_time) {
            return $max_attempts;
        }
        
        return max(0, $max_attempts - $attempts['count']);
    }
}

// =============================================
// AUTHENTICATION FUNCTIONS
// =============================================

/**
 * Authenticate user
 * 
 * @param string $username
 * @param string $password
 * @param bool $remember
 * @return array|false User data or false on failure
 */
if (!function_exists('authenticate_user')) {
    function authenticate_user($username, $password, $remember = false) {
        // Check if db functions exist
        if (!function_exists('db_fetch_one') || !function_exists('db_update')) {
            error_log("Database functions not available for authentication");
            return ['error' => 'system_error'];
        }
        
        // Check login attempts
        if (!check_login_attempts($username)) {
            audit_log(null, 'login_failed', 'users', null, null, [
                'username' => $username,
                'reason' => 'Too many attempts'
            ]);
            return ['error' => 'too_many_attempts'];
        }
        
        // Get user by username or email
        $user = db_fetch_one(
            "SELECT * FROM users WHERE (username = ? OR email = ?) AND is_active = 1",
            [$username, $username]
        );
        
        error_log("Login attempt - Username: $username");
        error_log("User found: " . ($user ? 'Yes' : 'No'));
        
        if (!$user) {
            audit_log(null, 'login_failed', 'users', null, null, [
                'username' => $username,
                'reason' => 'User not found'
            ]);
            return ['error' => 'invalid_credentials'];
        }
        
        if (!password_verify($password, $user['password_hash'])) {
            audit_log($user['user_id'], 'login_failed', 'users', $user['user_id'], null, [
                'reason' => 'Invalid password'
            ]);
            return ['error' => 'invalid_credentials'];
        }
        
        $bcrypt_cost = defined('BCRYPT_COST') ? BCRYPT_COST : 12;
        
        if (password_needs_rehash($user['password_hash'], PASSWORD_DEFAULT, ['cost' => $bcrypt_cost])) {
            $new_hash = password_hash($password, PASSWORD_DEFAULT, ['cost' => $bcrypt_cost]);
            db_update('users', ['password_hash' => $new_hash], 'user_id = ?', [$user['user_id']]);
            error_log("Password rehashed for user: " . $user['username']);
        }
        
        reset_login_attempts($username);
        
        db_update('users', [
            'last_login' => date('Y-m-d H:i:s'),
            'last_login_ip' => get_client_ip()
        ], 'user_id = ?', [$user['user_id']]);
        
        // Regenerate session ID for security
        session_regenerate_id(true);
        
        $_SESSION['user_id'] = $user['user_id'];
        $_SESSION['username'] = $user['username'];
        $_SESSION['user_role'] = $user['role_id'];
        $_SESSION['login_time'] = time();
        $_SESSION['ip_address'] = get_client_ip();
        $_SESSION['user_agent'] = get_user_agent();
        $_SESSION['authenticated'] = true;
        
        error_log("Login successful for user: " . $user['username']);
        
        if ($remember) {
            create_remember_token($user['user_id']);
        }
        
        audit_log($user['user_id'], 'login', 'users', $user['user_id']);
        
        create_notification(
            $user['user_id'],
            'info',
            'New Login',
            'You logged in from ' . get_client_ip(),
            null
        );
        
        return $user;
    }
}

/**
 * Create remember me token
 * 
 * @param int $user_id
 */
if (!function_exists('create_remember_token')) {
    function create_remember_token($user_id) {
        $token = bin2hex(random_bytes(32));
        $hashed_token = hash('sha256', $token);
        
        if (function_exists('db_update')) {
            db_update('users', [
                'remember_token' => $hashed_token
            ], 'user_id = ?', [$user_id]);
        }
        
        setcookie('remember_token', $token, [
            'expires' => time() + 2592000,
            'path' => '/',
            'secure' => isset($_SERVER['HTTPS']),
            'httponly' => true,
            'samesite' => 'Strict'
        ]);
    }
}

/**
 * Check remember me token
 */
if (!function_exists('check_remember_token')) {
    function check_remember_token() {
        if (!isset($_COOKIE['remember_token'])) {
            return false;
        }
        
        $token = $_COOKIE['remember_token'];
        $hashed_token = hash('sha256', $token);
        
        if (!function_exists('db_fetch_one')) {
            return false;
        }
        
        $user = db_fetch_one(
            "SELECT * FROM users WHERE remember_token = ? AND is_active = 1",
            [$hashed_token]
        );
        
        if ($user) {
            session_regenerate_id(true);
            $_SESSION['user_id'] = $user['user_id'];
            $_SESSION['username'] = $user['username'];
            $_SESSION['user_role'] = $user['role_id'];
            $_SESSION['login_time'] = time();
            $_SESSION['authenticated'] = true;
            return true;
        }
        
        setcookie('remember_token', '', time() - 3600, '/');
        return false;
    }
}

/**
 * Logout user
 */
if (!function_exists('logout_user')) {
    function logout_user() {
        if (is_logged_in()) {
            $user_id = current_user_id();
            
            if (function_exists('db_update')) {
                db_update('users', ['remember_token' => null], 'user_id = ?', [$user_id]);
            }
            
            setcookie('remember_token', '', time() - 3600, '/');
            
            audit_log($user_id, 'logout', 'users', $user_id);
        }
        
        $_SESSION = [];
        
        if (ini_get("session.use_cookies")) {
            $params = session_get_cookie_params();
            setcookie(
                session_name(),
                '',
                time() - 42000,
                $params["path"],
                $params["domain"],
                $params["secure"],
                $params["httponly"]
            );
        }
        
        session_destroy();
    }
}

// =============================================
// SESSION VALIDATION
// =============================================

/**
 * Validate current session
 * 
 * @return bool
 */
if (!function_exists('validate_session')) {
    function validate_session() {
        if (!is_logged_in()) {
            return false;
        }
        
        $session_timeout = defined('SESSION_TIMEOUT') ? SESSION_TIMEOUT : 7200;
        
        if (time() - $_SESSION['login_time'] > $session_timeout) {
            logout_user();
            return false;
        }
        
        // Optional IP check (commented out to prevent issues with dynamic IPs)
        // if ($_SESSION['ip_address'] !== get_client_ip()) {
        //     log_message("Session IP mismatch for user {$_SESSION['user_id']}", 'WARNING');
        // }
        
        if (!function_exists('db_fetch_one')) {
            return true; // Can't validate further, but session exists
        }
        
        $user = db_fetch_one(
            "SELECT is_active FROM users WHERE user_id = ?",
            [$_SESSION['user_id']]
        );
        
        if (!$user || !$user['is_active']) {
            logout_user();
            return false;
        }
        
        $_SESSION['login_time'] = time();
        
        return true;
    }
}

// =============================================
// AUTHORIZATION FUNCTIONS
// =============================================

/**
 * Check if user has permission
 * 
 * @param string $permission_key
 * @param int|null $user_id
 * @return bool
 */
if (!function_exists('has_permission')) {
    function has_permission($permission_key, $user_id = null) {
        if (!$user_id) {
            $user_id = current_user_id();
        }
        
        if (!$user_id) {
            return false;
        }
        
        static $permissions_cache = [];
        
        $cache_key = $user_id . '_' . $permission_key;
        if (isset($permissions_cache[$cache_key])) {
            return $permissions_cache[$cache_key];
        }
        
        if (!function_exists('db_fetch_one') || !function_exists('db_fetch_value')) {
            $permissions_cache[$cache_key] = false;
            return false;
        }
        
        $user = db_fetch_one("SELECT role_id FROM users WHERE user_id = ?", [$user_id]);
        if (!$user) {
            $permissions_cache[$cache_key] = false;
            return false;
        }
        
        if ($user['role_id'] == 1) {
            $permissions_cache[$cache_key] = true;
            return true;
        }
        
        $sql = "
            SELECT COUNT(*) 
            FROM role_permissions rp
            JOIN permissions p ON rp.permission_id = p.permission_id
            WHERE rp.role_id = ? AND p.permission_key = ?
        ";
        
        $has_permission = db_fetch_value($sql, [$user['role_id'], $permission_key]) > 0;
        $permissions_cache[$cache_key] = $has_permission;
        
        return $has_permission;
    }
}

/**
 * Check if user has any of the given permissions
 * 
 * @param array $permission_keys
 * @param int|null $user_id
 * @return bool
 */
if (!function_exists('has_any_permission')) {
    function has_any_permission($permission_keys, $user_id = null) {
        foreach ($permission_keys as $key) {
            if (has_permission($key, $user_id)) {
                return true;
            }
        }
        return false;
    }
}

/**
 * Check if user has all of the given permissions
 * 
 * @param array $permission_keys
 * @param int|null $user_id
 * @return bool
 */
if (!function_exists('has_all_permissions')) {
    function has_all_permissions($permission_keys, $user_id = null) {
        foreach ($permission_keys as $key) {
            if (!has_permission($key, $user_id)) {
                return false;
            }
        }
        return true;
    }
}

/**
 * Get current user
 * 
 * @return array|null
 */
if (!function_exists('current_user')) {
    function current_user() {
        if (!is_logged_in()) {
            return null;
        }
        
        static $user = null;
        
        if ($user === null && function_exists('db_fetch_one')) {
            $user = db_fetch_one(
                "SELECT * FROM users WHERE user_id = ?",
                [$_SESSION['user_id']]
            );
        }
        
        return $user;
    }
}

// =============================================
// AUTHENTICATION MIDDLEWARE
// =============================================

/**
 * Require authentication - FIXED VERSION
 */
if (!function_exists('require_auth')) {
    function require_auth() {
        error_log("require_auth called - Checking session");
        
        if (!validate_session()) {
            error_log("validate_session failed, checking remember token");
            
            if (!check_remember_token()) {
                error_log("No valid session or remember token - redirecting to login");
                
                if (function_exists('set_flash_message')) {
                    set_flash_message('warning', 'Please log in to continue');
                }
                
                if (is_ajax_request()) {
                    json_error('Authentication required', null, 401);
                }
                
                $redirect = urlencode($_SERVER['REQUEST_URI']);
                
                // Use the correct path for login
                if (is_in_public_dir()) {
                    redirect('login.php?redirect=' . $redirect);
                } else {
                    redirect('public/login.php?redirect=' . $redirect);
                }
            } else {
                error_log("Remember token worked - user authenticated");
            }
        } else {
            error_log("Session validated successfully");
        }
    }
}

/**
 * Require permission - FIXED VERSION
 * 
 * @param string $permission_key
 */
if (!function_exists('require_permission')) {
    function require_permission($permission_key) {
        require_auth();
        
        if (!has_permission($permission_key)) {
            if (function_exists('audit_log')) {
                audit_log(current_user_id(), 'access_denied', null, null, null, [
                    'permission' => $permission_key,
                    'uri' => $_SERVER['REQUEST_URI']
                ]);
            }
            
            if (is_ajax_request()) {
                json_error('You do not have permission to perform this action', null, 403);
            }
            
            if (function_exists('set_flash_message')) {
                set_flash_message('danger', 'You do not have permission to access this page');
            }
            
            if (is_in_public_dir()) {
                redirect('access-denied.php');
            } else {
                redirect('public/access-denied.php');
            }
        }
    }
}

/**
 * Require any of the given permissions - FIXED VERSION
 * 
 * @param array $permission_keys
 */
if (!function_exists('require_any_permission')) {
    function require_any_permission($permission_keys) {
        require_auth();
        
        if (!has_any_permission($permission_keys)) {
            if (is_ajax_request()) {
                json_error('You do not have permission to perform this action', null, 403);
            }
            
            if (function_exists('set_flash_message')) {
                set_flash_message('danger', 'You do not have permission to access this page');
            }
            
            if (is_in_public_dir()) {
                redirect('access-denied.php');
            } else {
                redirect('public/access-denied.php');
            }
        }
    }
}

/**
 * Require specific role - FIXED VERSION
 * 
 * @param int|array $role_ids
 */
if (!function_exists('require_role')) {
    function require_role($role_ids) {
        require_auth();
        
        if (!is_array($role_ids)) {
            $role_ids = [$role_ids];
        }
        
        if (!in_array(current_user_role(), $role_ids)) {
            if (is_ajax_request()) {
                json_error('You do not have permission to perform this action', null, 403);
            }
            
            if (function_exists('set_flash_message')) {
                set_flash_message('danger', 'You do not have permission to access this page');
            }
            
            if (is_in_public_dir()) {
                redirect('access-denied.php');
            } else {
                redirect('public/access-denied.php');
            }
        }
    }
}

/**
 * Guest only (redirect if logged in) - FIXED VERSION
 */
if (!function_exists('guest_only')) {
    function guest_only() {
        if (validate_session()) {
            if (is_in_public_dir()) {
                redirect('dashboard.php');
            } else {
                redirect('public/dashboard.php');
            }
        }
    }
}

// =============================================
// PASSWORD MANAGEMENT
// =============================================

/**
 * Generate password reset token
 * 
 * @param string $email
 * @return string|false Token or false on failure
 */
if (!function_exists('generate_password_reset_token')) {
    function generate_password_reset_token($email) {
        if (!function_exists('db_fetch_one') || !function_exists('db_update')) {
            return false;
        }
        
        $user = db_fetch_one(
            "SELECT user_id FROM users WHERE email = ? AND is_active = 1",
            [$email]
        );
        
        if (!$user) {
            return false;
        }
        
        $token = bin2hex(random_bytes(32));
        $expires = date('Y-m-d H:i:s', time() + (defined('PASSWORD_RESET_EXPIRY') ? PASSWORD_RESET_EXPIRY : 3600));
        
        db_update('users', [
            'password_reset_token' => $token,
            'password_reset_expires' => $expires
        ], 'user_id = ?', [$user['user_id']]);
        
        return $token;
    }
}

/**
 * Validate password reset token
 * 
 * @param string $token
 * @return int|false User ID or false on failure
 */
if (!function_exists('validate_password_reset_token')) {
    function validate_password_reset_token($token) {
        if (!function_exists('db_fetch_one')) {
            return false;
        }
        
        $user = db_fetch_one(
            "SELECT user_id FROM users WHERE password_reset_token = ? AND password_reset_expires > NOW() AND is_active = 1",
            [$token]
        );
        
        return $user ? $user['user_id'] : false;
    }
}

/**
 * Reset password using token
 * 
 * @param string $token
 * @param string $new_password
 * @return bool
 */
if (!function_exists('reset_password_with_token')) {
    function reset_password_with_token($token, $new_password) {
        $user_id = validate_password_reset_token($token);
        
        if (!$user_id || !function_exists('db_update')) {
            return false;
        }
        
        $bcrypt_cost = defined('BCRYPT_COST') ? BCRYPT_COST : 12;
        $password_hash = password_hash($new_password, PASSWORD_DEFAULT, ['cost' => $bcrypt_cost]);
        
        db_update('users', [
            'password_hash' => $password_hash,
            'password_reset_token' => null,
            'password_reset_expires' => null
        ], 'user_id = ?', [$user_id]);
        
        if (function_exists('audit_log')) {
            audit_log($user_id, 'password_reset', 'users', $user_id);
        }
        
        return true;
    }
}

/**
 * Change password for logged in user
 * 
 * @param string $current_password
 * @param string $new_password
 * @return bool|string True on success, error message on failure
 */
if (!function_exists('change_password')) {
    function change_password($current_password, $new_password) {
        $user_id = current_user_id();
        
        if (!$user_id) {
            return 'Not logged in';
        }
        
        if (!function_exists('db_fetch_one') || !function_exists('db_update')) {
            return 'System error';
        }
        
        $user = db_fetch_one(
            "SELECT password_hash FROM users WHERE user_id = ?",
            [$user_id]
        );
        
        if (!password_verify($current_password, $user['password_hash'])) {
            return 'Current password is incorrect';
        }
        
        if (!preg_match('/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/', $new_password)) {
            return 'Password must be at least 8 characters and contain uppercase, lowercase, number, and special character';
        }
        
        $bcrypt_cost = defined('BCRYPT_COST') ? BCRYPT_COST : 12;
        $password_hash = password_hash($new_password, PASSWORD_DEFAULT, ['cost' => $bcrypt_cost]);
        
        db_update('users', [
            'password_hash' => $password_hash
        ], 'user_id = ?', [$user_id]);
        
        if (function_exists('audit_log')) {
            audit_log($user_id, 'password_change', 'users', $user_id);
        }
        
        return true;
    }
}

// =============================================
// INITIALIZATION
// =============================================

// Check remember me token if not logged in
if (!is_logged_in() && isset($_COOKIE['remember_token'])) {
    error_log("Checking remember token on init");
    check_remember_token();
}

// Validate session if logged in
if (is_logged_in()) {
    error_log("Validating session on init");
    validate_session();
}