<?php
require_once __DIR__ . '/includes/init.php';
require_once __DIR__ . '/includes/login_lockout_helper.php';
require_once __DIR__ . '/includes/login_email_otp_helper.php';

// 登录日志记录函数
function logLoginAttempt($type, $message, $data = []) {
    // 使用统一的日志目录（如果已定义），否则使用默认路径
    if (defined('LOG_PATH') && !empty(LOG_PATH)) {
        $logDir = LOG_PATH;
        // 规范化路径（移除末尾的斜杠，避免重复）
        $logDir = rtrim($logDir, '/\\');
        // 检查LOG_PATH是否已经是logs目录，如果是，直接使用；如果不是，需要拼接logs
        // 但通常LOG_PATH应该已经是完整路径（如 /www/wwwroot/ggai-os7/logs）
        // 如果LOG_PATH是 /logs，说明配置有问题，需要修正
        if ($logDir === '/logs' || $logDir === '\\logs') {
            // LOG_PATH配置错误，使用项目根目录下的logs
            $logDir = __DIR__ . '/logs';
            error_log("[LOGIN LOG WARNING] LOG_PATH配置可能有问题，使用默认路径: {$logDir}");
        }
    } else {
        $logDir = __DIR__ . '/logs';
    }
    
    // 确保目录存在，并设置安全权限
    if (!is_dir($logDir)) {
        // Linux/Unix: 0755 (所有者读写执行，组和其他人读执行)
        // Windows: 忽略权限设置
        $dirPerm = IS_WINDOWS ? null : 0755;
        $mkdirResult = @mkdir($logDir, $dirPerm, true);
        if (!$mkdirResult && !is_dir($logDir)) {
            // 目录创建失败，记录到PHP错误日志
            error_log("[LOGIN LOG ERROR] 无法创建日志目录: {$logDir}");
            // 尝试使用系统临时目录作为备用
            $logDir = sys_get_temp_dir() . '/ggai_login_logs';
            @mkdir($logDir, $dirPerm, true);
        } else if ($mkdirResult && !IS_WINDOWS) {
            // 设置目录权限（Linux/Unix）
            @chmod($logDir, 0755);
        }
    }
    
    // 确保目录可写
    if (!is_writable($logDir)) {
        error_log("[LOGIN LOG ERROR] 日志目录不可写: {$logDir}");
        // 尝试使用系统临时目录作为备用
        $logDir = sys_get_temp_dir() . '/ggai_login_logs';
        $dirPerm = IS_WINDOWS ? null : 0755;
        @mkdir($logDir, $dirPerm, true);
        if (!IS_WINDOWS) {
            @chmod($logDir, 0755);
        }
        if (!is_writable($logDir)) {
            error_log("[LOGIN LOG ERROR] 备用日志目录也不可写: {$logDir}");
            return; // 无法写入，直接返回
        }
    }
    
    $logFile = $logDir . '/loginuser.log';
    
    $timestamp = date('Y-m-d H:i:s');
    $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
    $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? 'unknown';
    $host = $_SERVER['HTTP_HOST'] ?? 'unknown';
    $requestUri = $_SERVER['REQUEST_URI'] ?? 'unknown';
    
    // 隐藏敏感信息（仅隐藏密码，保留完整用户名用于排查）
    $safeData = $data;
    // 密码不记录（安全考虑）
    if (isset($safeData['password'])) {
        unset($safeData['password']);
    }
    // 用户名完整记录（用于排查登录问题）
    
    $logEntry = [
        'time' => $timestamp,
        'type' => $type, // SUCCESS, FAILED, ERROR, WARNING, INFO
        'message' => $message,
        'ip' => $ip,
        'host' => $host,
        'uri' => $requestUri,
        'user_agent' => substr($userAgent, 0, 100), // 限制长度
        'session_id' => session_id() ?: 'none',
        'session_status' => session_status() === PHP_SESSION_ACTIVE ? 'active' : 'inactive',
        'cookie_domain' => ini_get('session.cookie_domain') ?: 'not_set',
        'data' => $safeData,
        'log_file_path' => $logFile // 添加日志文件路径，便于调试
    ];
    
    // 添加SESSION状态信息
    // 注意：需要先确保SESSION已启动才能读取数据
    // 如果SESSION已关闭但有ID，尝试重新启动以读取数据（用于日志记录）
    $sessionWasActive = session_status() === PHP_SESSION_ACTIVE;
    $sessionRestarted = false;
    
    if (!$sessionWasActive && session_id() && !empty(session_id())) {
        // SESSION已关闭但有ID，尝试重新启动读取数据（只读模式，用于日志）
        try {
            @session_start();
            $sessionRestarted = true;
        } catch (Exception $e) {
            // 启动失败，忽略
        }
    }
    
    if (session_status() === PHP_SESSION_ACTIVE) {
        // 尝试读取SESSION数据（如果SESSION已启动）
        $logEntry['session_user_id'] = isset($_SESSION['user_id']) ? $_SESSION['user_id'] : 'not_set';
        $logEntry['session_username'] = isset($_SESSION['username']) ? $_SESSION['username'] : 'not_set'; // 完整用户名
        
        // 如果刚才重新启动了SESSION，关闭它（避免影响后续流程）
        if ($sessionRestarted) {
            @session_write_close();
        }
    } else {
        // SESSION未启动，无法读取数据
        $logEntry['session_user_id'] = 'session_not_active';
        $logEntry['session_username'] = 'session_not_active';
    }
    
    // 添加Redis状态（如果可用）
    if (extension_loaded('redis') && defined('SESSION_REDIS_HOST')) {
        try {
            $testRedis = new Redis();
            $testRedis->connect(SESSION_REDIS_HOST, defined('SESSION_REDIS_PORT') ? SESSION_REDIS_PORT : 6379, 1);
            if (defined('SESSION_REDIS_AUTH') && !empty(SESSION_REDIS_AUTH)) {
                $testRedis->auth(SESSION_REDIS_AUTH);
            }
            $logEntry['redis_status'] = 'connected';
            $testRedis->close();
        } catch (Exception $e) {
            $logEntry['redis_status'] = 'failed: ' . $e->getMessage();
        }
    } else {
        $logEntry['redis_status'] = 'not_configured';
    }
    
    $logLine = json_encode($logEntry, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . PHP_EOL;
    
    // 尝试写入日志文件
    $writeResult = @file_put_contents($logFile, $logLine, FILE_APPEND | LOCK_EX);
    
    // 设置日志文件权限（Linux/Unix: 0644，所有者读写，其他人只读）
    if ($writeResult !== false && !IS_WINDOWS && file_exists($logFile)) {
        @chmod($logFile, 0644);
    }
    
    // 如果写入失败，记录到PHP错误日志
    if ($writeResult === false) {
        $error = error_get_last();
        error_log("[LOGIN LOG ERROR] 无法写入日志文件: {$logFile}, 错误: " . ($error['message'] ?? 'unknown'));
        // 同时尝试写入到PHP错误日志
        error_log("[LOGIN LOG] " . $logLine);
    }
}

// 如果URL中有logout参数，确保清除所有SESSION数据（防止自动登录）
if (isset($_GET['logout'])) {
    // 只清除“当前会话”的登录token，避免影响其他浏览器/机器的并存登录
    // 优先使用 session 内保存的 token；如果客户端带了 localStorage_token 也支持按 token 删除
    $tokenToDelete = $_SESSION['user_login_token'] ?? ($_POST['localStorage_token'] ?? ($_GET['localStorage_token'] ?? null));
    if ($tokenToDelete) {
        try {
            $db = Database::getInstance()->getConnection();
            $stmt = $db->prepare("DELETE FROM user_login_tokens WHERE token = ?");
            $stmt->execute([$tokenToDelete]);
        } catch (Exception $e) {
            error_log("[LOGOUT] 清除当前token失败: " . $e->getMessage());
        }
    }
    
    $_SESSION = array();
    if (ini_get('session.use_cookies')) {
        $params = session_get_cookie_params();
        $cookieName = session_name();
        setcookie($cookieName, '', time() - 3600, $params['path'], $params['domain'], $params['secure'], $params['httponly']);
        $cookieDomain = ini_get('session.cookie_domain');
        if ($cookieDomain) {
            setcookie($cookieName, '', time() - 3600, $params['path'], $cookieDomain, $params['secure'], $params['httponly']);
        }
    }
    session_destroy();
    session_start(); // 重新启动SESSION
    $_SESSION = array(); // 确保SESSION为空
}

// 登录后安全回跳（?return= 或 ?redirect= ，仅允许 /user/… 站内路径）
$ggaiLoginReturn = '';
if (!empty($_GET['return'])) {
    $ggaiLoginReturn = ggai_sanitize_login_return_path((string) $_GET['return']);
}
if ($ggaiLoginReturn === '' && !empty($_GET['redirect'])) {
    $ggaiLoginReturn = ggai_sanitize_login_return_path((string) $_GET['redirect']);
}

// 如果已登录，跳转到用户中心或安全 return
if (isset($_SESSION['user_id'])) {
    if ($ggaiLoginReturn !== '') {
        header('Location: ' . $ggaiLoginReturn);
        exit;
    }
    header('Location: user/');
    exit;
}

$page_title = __t('auth_login_page_title', '用户登录');
$error = '';
$loginOtpEnabled = function_exists('ggai_login_email_otp_enabled') && ggai_login_email_otp_enabled();
if (isset($_GET['restart_login']) && function_exists('ggai_login_email_otp_clear_pending')) {
    ggai_login_email_otp_clear_pending();
    header('Location: login.php');
    exit;
}

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $loginStartTime = microtime(true);
    $username = '';
    $password = '';
    
    try {
        // —— 同页发送登录邮箱验证码（须先填账号+密码）——
        if (!empty($_POST['send_login_otp'])) {
            header('Content-Type: application/json; charset=UTF-8');
            $dbMail = (isset($pdo_master) && $pdo_master !== null) ? $pdo_master : $pdo;
            $u = trim((string) ($_POST['username'] ?? ''));
            $p = trim((string) ($_POST['password'] ?? ''));
            $u = str_replace('　', '', $u);
            $p = str_replace('　', '', $p);
            if ($u === '' || $p === '') {
                echo json_encode(['success' => false, 'msg' => '请先填写账号和密码'], JSON_UNESCAPED_UNICODE);
                exit;
            }
            if (isset($pdo) && $pdo instanceof PDO && function_exists('security_ban_guard_client_ip')) {
                $ipGate = security_ban_guard_client_ip($pdo);
                if (empty($ipGate['ok'])) {
                    echo json_encode(['success' => false, 'msg' => '暂时无法完成操作，请稍后重试'], JSON_UNESCAPED_UNICODE);
                    exit;
                }
            }
            $lockCheck = ggai_login_lockout_check($u);
            if (empty($lockCheck['ok'])) {
                echo json_encode(['success' => false, 'msg' => (string) ($lockCheck['error'] ?? '请稍后再试')], JSON_UNESCAPED_UNICODE);
                exit;
            }
            $stmt = $dbMail->prepare("SELECT id, username, password, status, role FROM users WHERE username = ? AND role = 'user' LIMIT 1");
            $stmt->execute([$u]);
            $userRow = $stmt->fetch(PDO::FETCH_ASSOC);
            if (!$userRow) {
                $stmt = $dbMail->prepare("SELECT id, username, password, status, role FROM users WHERE (email = ? OR phone = ?) AND role = 'user' LIMIT 1");
                $stmt->execute([$u, $u]);
                $userRow = $stmt->fetch(PDO::FETCH_ASSOC);
            }
            if (!$userRow) {
                $stmt = $dbMail->prepare("SELECT id, username, password, status, role FROM users WHERE nickname = ? AND role = 'user' LIMIT 1");
                $stmt->execute([$u]);
                $userRow = $stmt->fetch(PDO::FETCH_ASSOC);
            }
            if (!$userRow) {
                ggai_login_lockout_on_fail($u);
                echo json_encode(['success' => false, 'msg' => '账号或密码错误'], JSON_UNESCAPED_UNICODE);
                exit;
            }
            $encryption = Encryption::getInstance();
            if (!$encryption->verifyPassword($p, $userRow['password'])) {
                ggai_login_lockout_on_fail($u, null, (int) $userRow['id']);
                echo json_encode(['success' => false, 'msg' => '账号或密码错误'], JSON_UNESCAPED_UNICODE);
                exit;
            }
            $statusOk = function_exists('security_ban_user_status_is_active')
                ? security_ban_user_status_is_active($userRow['status'])
                : ((string) $userRow['status'] === 'active');
            $listed = function_exists('security_ban_is_user_banned') && security_ban_is_user_banned($dbMail, (int) $userRow['id']);
            if (!$statusOk || $listed) {
                echo json_encode(['success' => false, 'msg' => '账号已被禁用，请联系客服'], JSON_UNESCAPED_UNICODE);
                exit;
            }
            $send = ggai_login_email_otp_begin($dbMail, $userRow, $u);
            echo json_encode([
                'success' => !empty($send['ok']),
                'msg' => (string) ($send['msg'] ?? ''),
                'masked' => (string) ($send['masked'] ?? ''),
                'wait' => (int) ($send['wait'] ?? (!empty($send['ok']) ? 60 : 0)),
            ], JSON_UNESCAPED_UNICODE);
            exit;
        }

        // 简化处理，只去除基本空白字符，保持中文用户名原样
        $username = trim($_POST['username'] ?? '');
        $password = trim($_POST['password'] ?? '');
        // 只去除全角空格，保持其他字符不变
        $username = str_replace('　', '', $username);
        $password = str_replace('　', '', $password);
        
        // 记录登录尝试
        logLoginAttempt('INFO', '登录尝试开始', [
            'username' => $username,
            'has_password' => !empty($password)
        ]);
        
        if (empty($username) || empty($password)) {
            logLoginAttempt('FAILED', '登录失败：用户名或密码为空', [
                'username' => $username,
                'has_password' => !empty($password)
            ]);
            throw new Exception(__t('auth_err_login_empty', '请输入用户名和密码'));
        }

        if (isset($pdo) && $pdo instanceof PDO && function_exists('security_ban_guard_client_ip')) {
            $ipGate = security_ban_guard_client_ip($pdo);
            if (empty($ipGate['ok'])) {
                logLoginAttempt('FAILED', '登录失败：IP黑名单', [
                    'username' => $username,
                    'ip' => function_exists('getClientIP') ? getClientIP() : '',
                ]);
                throw new Exception($ipGate['msg'] ?: '访问受限');
            }
        }

        $lockCheck = ggai_login_lockout_check($username);
        if (!$lockCheck['ok']) {
            logLoginAttempt('FAILED', '登录失败：冷却中', [
                'username' => $username,
                'remain' => $lockCheck['remain'] ?? 0,
            ]);
            throw new Exception((string) $lockCheck['error']);
        }
        
        $db = (isset($pdo_master) && $pdo_master !== null) ? $pdo_master : $pdo;
        
        // 查询用户（支持 用户名/邮箱/手机/昵称 登录）
        try {
            // 优先精确匹配用户名，其次邮箱/手机，最后昵称（避免昵称撞车抢登录）
            $stmt = $db->prepare("SELECT id, username, password, status, role FROM users WHERE username = ? AND role = 'user' LIMIT 1");
            $stmt->execute([$username]);
            $user = $stmt->fetch(PDO::FETCH_ASSOC);
            $stmt->closeCursor();
            if (!$user) {
                $stmt = $db->prepare("SELECT id, username, password, status, role FROM users WHERE (email = ? OR phone = ?) AND role = 'user' LIMIT 1");
                $stmt->execute([$username, $username]);
                $user = $stmt->fetch(PDO::FETCH_ASSOC);
                $stmt->closeCursor();
            }
            if (!$user) {
                $stmt = $db->prepare("SELECT id, username, password, status, role FROM users WHERE nickname = ? AND role = 'user' LIMIT 1");
                $stmt->execute([$username]);
                $user = $stmt->fetch(PDO::FETCH_ASSOC);
                $stmt->closeCursor();
            }
        } catch (Exception $ex) {
            logLoginAttempt('ERROR', '数据库查询异常', [
                'username' => $username,
                'error' => $ex->getMessage(),
                'trace' => $ex->getTraceAsString()
            ]);
            error_log('[SQL ERROR] ' . date('Y-m-d H:i:s') . ': ' . $ex->getMessage());
            throw new Exception('数据库查询异常: '.$ex->getMessage());
        }
        
        if (!$user) {
            logLoginAttempt('FAILED', '登录失败：用户名不存在', [
                'username' => $username
            ]);
            $fail = ggai_login_lockout_on_fail($username);
            throw new Exception($fail['message'] ?? __t('auth_err_user_not_found', '用户名不存在'));
        }
        
        // 验证密码
        $encryption = Encryption::getInstance();
        if (!$encryption->verifyPassword($password, $user['password'])) {
            logLoginAttempt('FAILED', '登录失败：密码错误', [
                'username' => $username,
                'user_id' => $user['id']
            ]);
            $fail = ggai_login_lockout_on_fail($username, null, (int) $user['id']);
            // 严禁把明文密码/哈希写入 web 目录（历史 error_log.txt 曾因此公网可下载）
            error_log('[PWD ERROR] ' . date('Y-m-d H:i:s') . ' username=' . $username . ' user_id=' . (int) $user['id']);
            throw new Exception($fail['message'] ?? __t('auth_err_password_wrong', '密码错误'));
        }
        
        // 检查账号状态（兼容 active / 1 / enabled）
        $statusOk = function_exists('security_ban_user_status_is_active')
            ? security_ban_user_status_is_active($user['status'])
            : ((string) $user['status'] === 'active');
                $listed = isset($pdo) && $pdo instanceof PDO && function_exists('security_ban_is_user_banned')
            && security_ban_is_user_banned($pdo, (int) $user['id']);
if (!$statusOk || $listed) {
            logLoginAttempt('FAILED', '登录失败：账号已被禁用', [
                'username' => $username,
                'user_id' => $user['id'],
                'status' => $user['status'],
                'security_user_ban' => !empty($listed) ? 1 : 0,
            ]);
            throw new Exception(__t('auth_err_account_disabled', '账号已被禁用，请联系客服'));
        }

        // 同页二次验证：账号+密码+邮箱验证码一起校验
        if (function_exists('ggai_login_email_otp_enabled') && ggai_login_email_otp_enabled()) {
            $otpCode = trim((string) ($_POST['login_otp_code'] ?? ''));
            if ($otpCode === '') {
                throw new Exception('请填写邮箱验证码（先点发送，再填最新邮件中的 6 位码）');
            }
            $otpChk = ggai_login_email_otp_check_for_user(
                $db instanceof PDO ? $db : $pdo,
                $user,
                $otpCode
            );
            if (empty($otpChk['ok'])) {
                logLoginAttempt('FAILED', '登录失败：二次验证码错误', [
                    'username' => $username,
                    'user_id' => $user['id'],
                ]);
                throw new Exception((string) ($otpChk['msg'] ?? '验证码错误或已过期'));
            }
            logLoginAttempt('INFO', '密码与验证码均通过', [
                'username' => $username,
                'user_id' => $user['id'],
            ]);
        }

        login_finalize_label:
        ggai_login_lockout_on_success($username);
        
        logLoginAttempt('INFO', '用户验证通过，开始设置SESSION', [
            'username' => $username,
            'user_id' => $user['id']
        ]);
        
        // 设置登录状态
        $_SESSION['user_id'] = $user['id'];
        $_SESSION['username'] = $user['username'];
        $_SESSION['role'] = $user['role'];
        $_SESSION['last_activity'] = time(); // 设置最后活动时间
        $_SESSION['login_time'] = time(); // 记录登录时间
        
        // Redis SESSION兼容：先保存数据，确保数据写入Redis
        // 重要：在Redis环境下，必须先写入数据，再重新生成ID
        // 使用安全的session_write_close，如果Redis失败则自动回退到文件存储
        require_once __DIR__ . '/includes/session_fallback_helper.php';
        $oldSessionId = session_id();
        safe_session_write_close(); // 先保存当前SESSION数据（Redis或文件存储）
        
        // 验证数据是否已写入Redis（可选，用于调试）
        if (defined('DEBUG') && DEBUG && extension_loaded('redis')) {
            try {
                $verify_redis = new Redis();
                $verify_connect = $verify_redis->connect(
                    defined('SESSION_REDIS_HOST') ? SESSION_REDIS_HOST : '127.0.0.1',
                    defined('SESSION_REDIS_PORT') ? SESSION_REDIS_PORT : 6379,
                    2
                );
                if ($verify_connect) {
                    if (defined('SESSION_REDIS_AUTH') && !empty(SESSION_REDIS_AUTH)) {
                        $verify_redis->auth(SESSION_REDIS_AUTH);
                    }
                    $old_session_key = (defined('SESSION_REDIS_PREFIX') ? SESSION_REDIS_PREFIX : 'PHPREDIS_SESSION:') . $oldSessionId;
                    $old_session_data = $verify_redis->get($old_session_key);
                    if ($old_session_data) {
                        error_log("[LOGIN DEBUG] 旧SESSION数据已写入Redis: " . $oldSessionId);
                    } else {
                        error_log("[LOGIN WARNING] 旧SESSION数据未写入Redis: " . $oldSessionId);
                    }
                    $verify_redis->close();
                }
            } catch (Exception $e) {
                // 忽略验证错误
            }
        }
        
        // 重新启动SESSION（此时数据已在Redis或文件存储中）
        safe_session_start(); // 使用安全的session_start，如果Redis失败则自动回退
        
        // 重新生成SESSION ID（提高安全性，防止会话固定攻击）
        // 注意：使用true参数，删除旧SESSION（避免Redis中残留数据）
        // 但我们需要先复制数据到新SESSION
        $temp_session_data = [
            'user_id' => $user['id'],
            'username' => $user['username'],
            'role' => $user['role'],
            'last_activity' => time(),
            'login_time' => time()
        ];
        
        // 重新生成SESSION ID
        // 注意：使用 false 参数，不删除旧Session，允许多设备同时登录
        session_regenerate_id(false);
        
        // 重新设置SESSION数据（确保新SESSION ID也有数据）
        $_SESSION['user_id'] = $temp_session_data['user_id'];
        $_SESSION['username'] = $temp_session_data['username'];
        $_SESSION['role'] = $temp_session_data['role'];
        $_SESSION['last_activity'] = $temp_session_data['last_activity'];
        $_SESSION['login_time'] = $temp_session_data['login_time'];
        if (function_exists('generate_csrf_token')) {
            generate_csrf_token();
        }
        $csrfForDual = (isset($_SESSION['csrf_token']) && is_string($_SESSION['csrf_token']) && $_SESSION['csrf_token'] !== '')
            ? $_SESSION['csrf_token']
            : null;
        
        // 立即保存，确保新SESSION ID的数据写入Redis或文件存储
        safe_session_write_close(); // 使用安全的session_write_close
        
        // 双重存储：同时保存到Redis和文件存储，提高可靠性
        $newSessionId = session_id();
        $session_data_to_store = [];
        $session_data_to_store['user_id'] = $temp_session_data['user_id'];
        $session_data_to_store['username'] = $temp_session_data['username'];
        $session_data_to_store['role'] = $temp_session_data['role'];
        $session_data_to_store['last_activity'] = $temp_session_data['last_activity'];
        $session_data_to_store['login_time'] = $temp_session_data['login_time'];
        if ($csrfForDual !== null && $csrfForDual !== '') {
            $session_data_to_store['csrf_token'] = $csrfForDual;
        }
        
        // 执行双重存储
        $dual_store_result = dual_store_session($newSessionId, $session_data_to_store);
        
        // 验证存储结果
        $sessionSaved = false;
        if ($dual_store_result) {
            // 至少有一个存储成功，验证数据
            $verify_data = dual_read_session($newSessionId);
            if ($verify_data && isset($verify_data['user_id']) && $verify_data['user_id'] == $user['id']) {
                $sessionSaved = true;
                error_log("[LOGIN SUCCESS] 双重存储成功，SESSION数据已保存到Redis和文件: " . $newSessionId);
            } else {
                // 双重存储失败，但可能PHP的session_write_close已保存，再次验证
                error_log("[LOGIN WARNING] 双重存储验证失败，检查PHP SESSION");
            }
        }
        
        // 重新启动SESSION，供后续使用
        safe_session_start(); // 使用安全的session_start
        
        // 再次验证SESSION数据（从PHP SESSION读取）
        if (!$sessionSaved) {
            $sessionSaved = isset($_SESSION['user_id']) && $_SESSION['user_id'] == $user['id'];
        }
        
        // 如果SESSION保存失败，强制重新设置（最后一次尝试）
        if (!$sessionSaved) {
            error_log("[LOGIN WARNING] SESSION保存失败，强制重新设置SESSION数据");
            $_SESSION['user_id'] = $user['id'];
            $_SESSION['username'] = $user['username'];
            $_SESSION['role'] = $user['role'];
            $_SESSION['last_activity'] = time();
            $_SESSION['login_time'] = time();
            safe_session_write_close();
            safe_session_start();
            // 再次验证
            $sessionSaved = isset($_SESSION['user_id']) && $_SESSION['user_id'] == $user['id'];
        }
        
        if (!$sessionSaved) {
            logLoginAttempt('ERROR', 'SESSION保存失败，user_id未正确保存', [
                'username' => $username,
                'user_id' => $user['id'],
                'session_id' => session_id(),
                'old_session_id' => $oldSessionId,
                'new_session_id' => $newSessionId,
                'session_data' => $_SESSION
            ]);
            error_log("[LOGIN ERROR] SESSION保存失败，user_id未正确保存，尝试使用localStorage备用方案");
            error_log("[LOGIN ERROR] SESSION ID: " . session_id() . ", 旧ID: " . $oldSessionId);
            error_log("[LOGIN ERROR] 当前SESSION数据: " . json_encode($_SESSION, JSON_UNESCAPED_UNICODE));
            
            // SESSION保存失败，抛出异常，让用户看到错误信息
            throw new Exception('登录状态保存失败，请重试。如问题持续，请联系客服。');
        } else {
            logLoginAttempt('INFO', 'SESSION保存成功', [
                'username' => $username,
                'user_id' => $user['id'],
                'session_id' => session_id(),
                'old_session_id' => $oldSessionId,
                'new_session_id' => $newSessionId
            ]);
            error_log("[LOGIN SUCCESS] SESSION已保存（双重存储），user_id=" . $user['id'] . ", SESSION ID: " . session_id());
        }
        
        // 移动端兼容：显式设置Cookie，确保安卓浏览器能正确保存
        $cookieParams = session_get_cookie_params();
        $cookieDomain = $cookieParams['domain'] ?: '';
        
        // 如果Cookie域名为空，尝试从SESSION配置中获取
        if (empty($cookieDomain) && defined('SESSION_DOMAIN') && SESSION_DOMAIN !== '') {
            $cookieDomain = SESSION_DOMAIN;
        }
        
        $sessionName = session_name();
        $sessionId = session_id();
        $currentCookieValue = $_COOKIE[$sessionName] ?? '';
        
        // 清掉历史遗留的 cookie（不同 path/domain 组合）
        $currentHost = $_SERVER['HTTP_HOST'] ?? '';
        $currentHost = preg_replace('/:\\d+$/', '', $currentHost);
        
        // 清掉 "/" 路径版本
        @setcookie($sessionName, '', [
            'expires' => time() - 3600,
            'path' => '/',
            'domain' => '',
            'secure' => $cookieParams['secure'],
            'httponly' => $cookieParams['httponly'],
            'samesite' => 'Lax'
        ]);
        
        // 清掉可能存在的 .主域名 版本
        if ($currentHost) {
            $parts = explode('.', $currentHost);
            if (count($parts) >= 2) {
                $mainDomain = $parts[count($parts) - 2] . '.' . $parts[count($parts) - 1];
                @setcookie($sessionName, '', [
                    'expires' => time() - 3600,
                    'path' => '/',
                    'domain' => '.' . $mainDomain,
                    'secure' => $cookieParams['secure'],
                    'httponly' => $cookieParams['httponly'],
                    'samesite' => 'Lax'
                ]);
            }
        }
        
        // 设置正确版本：Host-only domain, path=/
        $cookieSet = @setcookie($sessionName, $sessionId, [
            'expires' => time() + 86400,
            'path' => '/',
            'domain' => '', // Host-only
            'secure' => $cookieParams['secure'],
            'httponly' => $cookieParams['httponly'],
            'samesite' => 'Lax'
        ]);
        
        if ($cookieSet) {
            error_log("[USER LOGIN] Cookie已设置: name={$sessionName}, session_id=" . substr($sessionId, 0, 16) . "..., domain=Host-only, path=/, host={$currentHost}");
        } else {
            error_log("[USER LOGIN] Cookie设置失败: name={$sessionName}, session_id=" . substr($sessionId, 0, 16) . "...");
        }
        
        logLoginAttempt('INFO', 'Cookie已设置', [
            'username' => $username,
            'user_id' => $user['id'],
            'cookie_name' => $sessionName,
            'cookie_id' => substr($sessionId, 0, 16) . '...',
            'cookie_domain' => 'Host-only',
            'cookie_path' => '/',
            'cookie_set_result' => $cookieSet ? 'success' : 'failed'
        ]);
        error_log("[LOGIN] Cookie已设置: name=" . session_name() . ", id=" . session_id() . ", domain=" . $cookieDomain);
        
        // 生成登录Token，用于localStorage备用方案（无论Session是否成功都保存，作为备用）
        $loginToken = bin2hex(random_bytes(32)); // 64字符的随机token
        $tokenExpiry = time() + 86400; // 24小时有效期
        
        // 将token保存到数据库（用于验证）
        // 注意：这是写操作，必须使用主库
        try {
            // 获取主库连接（写操作必须用主库）
            global $pdo_master;
            $writeDb = function_exists('db_wait_for_master_connection')
                ? db_wait_for_master_connection()
                : ($pdo_master ?? $db);
            
            // 先检查表是否存在，如果不存在则创建
            $checkTable = $writeDb->query("SHOW TABLES LIKE 'user_login_tokens'");
            if ($checkTable->rowCount() == 0) {
                // 表不存在，创建表
                $createTableSql = "
                CREATE TABLE IF NOT EXISTS `user_login_tokens` (
                    `id` INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
                    `user_id` INT UNSIGNED NOT NULL,
                    `token` VARCHAR(64) NOT NULL UNIQUE,
                    `expires_at` DATETIME NOT NULL,
                    `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
                    `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                    INDEX `idx_user_id` (`user_id`),
                    INDEX `idx_token` (`token`),
                    INDEX `idx_expires_at` (`expires_at`)
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
                ";
                $writeDb->exec($createTableSql);
                error_log("[LOGIN] 已自动创建user_login_tokens表");
            }
            
            // 插入新token（允许同账号多端并存，不删除旧token）
            $stmt = $writeDb->prepare("
                INSERT INTO user_login_tokens (user_id, token, expires_at, created_at) 
                VALUES (?, ?, FROM_UNIXTIME(?), NOW())
            ");
            $stmt->execute([$user['id'], $loginToken, $tokenExpiry]);
            error_log("[LOGIN] Token已保存到数据库: user_id=" . $user['id']);

            // 清理过期token（全局）
            try {
                $writeDb->exec("DELETE FROM user_login_tokens WHERE expires_at < NOW()");
            } catch (Exception $cleanupEx) {
                // 忽略清理失败
            }

        if (isset($pdo) && $pdo instanceof PDO && function_exists('security_ban_guard_client_ip')) {
            $ipGate = security_ban_guard_client_ip($pdo);
            if (empty($ipGate['ok'])) {
                logLoginAttempt('FAILED', '登录失败：IP黑名单', [
                    'username' => $username,
                    'ip' => function_exists('getClientIP') ? getClientIP() : '',
                ]);
                throw new Exception($ipGate['msg'] ?: '访问受限');
            }
        }

            // 限制每个用户最多保留 20 个有效token（防止无限增长）
            try {
                $stmtCnt = $writeDb->prepare("SELECT COUNT(*) AS cnt FROM user_login_tokens WHERE user_id = ?");
                $stmtCnt->execute([$user['id']]);
                $cntRow = $stmtCnt->fetch(PDO::FETCH_ASSOC);
                $cnt = (int)($cntRow['cnt'] ?? 0);
                if ($cnt > 20) {
                    $toDelete = $cnt - 20;
                    // MySQL 支持 DELETE ... ORDER BY ... LIMIT
                    $stmtDel = $writeDb->prepare("DELETE FROM user_login_tokens WHERE user_id = ? ORDER BY created_at ASC LIMIT {$toDelete}");
                    $stmtDel->execute([$user['id']]);
                }
            } catch (Exception $limitEx) {
                // 忽略限制失败
            }
        } catch (Exception $tokenEx) {
            error_log("[LOGIN ERROR] Token保存失败: " . $tokenEx->getMessage());
            // Token保存失败不影响登录，继续执行（登录状态已保存在SESSION中）
        }

        // 记录当前会话 token（用于“只退出当前设备/浏览器”，不影响其他端）
        $_SESSION['user_login_token'] = $loginToken;
        
        // 更新用户最后登录时间和IP（写操作，必须使用主库）
        try {
            global $pdo_master;
            $writeDb = function_exists('db_wait_for_master_connection')
                ? db_wait_for_master_connection()
                : ($pdo_master ?? $db);
            
            $last_login = date('Y-m-d H:i:s');
            $login_ip = getClientIP();
            $stmt = $writeDb->prepare("UPDATE users SET last_login = ?, login_ip = ? WHERE id = ?");
            $stmt->execute([$last_login, $login_ip, $user['id']]);
            error_log("[LOGIN] 已更新用户登录信息: user_id=" . $user['id']);
        } catch (Exception $updateEx) {
            error_log("[LOGIN WARNING] 更新用户登录信息失败: " . $updateEx->getMessage());
            // 更新登录信息失败不影响登录，继续执行（登录状态已保存在SESSION中）
        }
        
        // 无论Session是否成功，都保存token到localStorage作为备用方案
        // 通过JavaScript将token保存到localStorage
        echo '<script>
        (function(){
            if(typeof(Storage) !== "undefined") {
                try {
                    localStorage.setItem("user_login_token", "' . $loginToken . '");
                    localStorage.setItem("user_id", "' . $user['id'] . '");
                    localStorage.setItem("user_login_time", "' . time() . '");
                    localStorage.setItem("user_token_expiry", "' . $tokenExpiry . '");
                    console.log("登录信息已保存到localStorage（备用方案）");
                } catch(e) {
                    console.error("localStorage保存失败:", e);
                }
            }
        })();
        </script>';

        // 同时把 token 写入 Cookie（服务端可直接读取，用于 GET 请求恢复登录）
        try {
            $cookieParams = session_get_cookie_params();
            $cookieDomain = '';
            if (defined('SESSION_DOMAIN') && SESSION_DOMAIN !== '') {
                $cookieDomain = SESSION_DOMAIN;
            } else {
                // 使用当前 session cookie_domain（init.php 已自动设为 .主域名）
                $cookieDomain = ini_get('session.cookie_domain') ?: '';
            }
            setcookie('user_login_token', $loginToken, [
                'expires' => $tokenExpiry,
                'path' => '/',
                'domain' => $cookieDomain,
                'secure' => $cookieParams['secure'],
                'httponly' => true,
                'samesite' => 'Lax'
            ]);
        } catch (Exception $e) {
            // ignore
        }
        
        // 记录登录日志（包含用户ID和IP地址）
        try {
            logSystemAction('login', '用户登录', [
                'username' => $user['username'],
                'ip' => getClientIP()
            ], $user['username'], $user['id']);
        } catch (Exception $logEx) {
            // 忽略日志记录错误，不影响登录
            error_log('Login log error: ' . $logEx->getMessage());
        }
        
        // 记录登录成功
        $loginDuration = isset($loginStartTime) ? round((microtime(true) - $loginStartTime) * 1000, 2) : 0;
        
        // 最终验证SESSION是否真的保存成功
        // 注意：在session_regenerate_id(true)后，需要重新启动SESSION才能读取新SESSION的数据
        safe_session_start(); // 确保SESSION已启动
        
        // 如果SESSION中没有数据，尝试从Redis或文件读取
        if (!isset($_SESSION['user_id']) || $_SESSION['user_id'] != $user['id']) {
            error_log("[LOGIN WARNING] SESSION中没有数据，尝试从Redis/文件读取");
            
            // 尝试从双重存储读取
            $currentSessionId = session_id();
            if ($currentSessionId) {
                $verify_data = dual_read_session($currentSessionId);
                if ($verify_data && isset($verify_data['user_id']) && $verify_data['user_id'] == $user['id']) {
                    // 从双重存储读取成功，同步到当前SESSION
                    $_SESSION['user_id'] = $verify_data['user_id'];
                    $_SESSION['username'] = $verify_data['username'] ?? $user['username'];
                    $_SESSION['role'] = $verify_data['role'] ?? $user['role'];
                    $_SESSION['last_activity'] = $verify_data['last_activity'] ?? time();
                    $_SESSION['login_time'] = $verify_data['login_time'] ?? time();
                    safe_session_write_close();
                    safe_session_start();
                    error_log("[LOGIN SUCCESS] 从双重存储恢复SESSION数据成功");
                }
            }
        }
        
        $finalSessionCheck = isset($_SESSION['user_id']) && $_SESSION['user_id'] == $user['id'];
        
        logLoginAttempt('SUCCESS', '登录成功', [
            'username' => $username,
            'user_id' => $user['id'],
            'session_id' => session_id(),
            'cookie_domain' => $cookieDomain,
            'duration_ms' => $loginDuration,
            'final_session_check' => $finalSessionCheck ? 'passed' : 'failed',
            'session_user_id_in_log' => $_SESSION['user_id'] ?? 'not_set'
        ]);
        
        // 如果SESSION验证失败，最后一次尝试：直接设置并保存
        if (!$finalSessionCheck) {
            error_log("[LOGIN WARNING] 最终验证失败，最后一次尝试：直接设置SESSION");
            $_SESSION['user_id'] = $user['id'];
            $_SESSION['username'] = $user['username'];
            $_SESSION['role'] = $user['role'];
            $_SESSION['last_activity'] = time();
            $_SESSION['login_time'] = time();
            
            // 立即保存
            safe_session_write_close();
            
            // 再次启动并验证
            safe_session_start();
            $finalSessionCheck = isset($_SESSION['user_id']) && $_SESSION['user_id'] == $user['id'];
            
            if (!$finalSessionCheck) {
                logLoginAttempt('ERROR', '登录成功但SESSION验证失败（所有尝试都失败）', [
                    'username' => $username,
                    'user_id' => $user['id'],
                    'session_id' => session_id(),
                    'session_data' => $_SESSION,
                    'session_status' => session_status()
                ]);
                error_log("[LOGIN CRITICAL] 登录成功但SESSION验证失败，user_id=" . $user['id'] . ", SESSION ID=" . session_id());
                error_log("[LOGIN CRITICAL] 当前SESSION内容: " . json_encode($_SESSION, JSON_UNESCAPED_UNICODE));
                error_log("[LOGIN CRITICAL] SESSION状态: " . session_status());
                
                // 抛出异常，让用户看到错误信息
                throw new Exception('登录状态保存失败，请重试。如问题持续，请联系客服。错误代码：SESSION_VERIFY_FAILED');
            } else {
                error_log("[LOGIN SUCCESS] 最后一次尝试成功，SESSION已保存");
            }
        }
        
        // 确保SESSION数据已写入
        safe_session_write_close();
        
        // 在重定向前，再次确保 session cookie 被正确设置（防止重定向后 cookie 丢失）
        $finalCookieCheck = session_id();
        $finalCookieName = session_name();
        $finalCookieValue = $_COOKIE[$finalCookieName] ?? '';
        if ($finalCookieCheck && $finalCookieValue !== $finalCookieCheck) {
            $cookieParams = session_get_cookie_params();
            @setcookie($finalCookieName, $finalCookieCheck, [
                'expires' => time() + 86400,
                'path' => '/',
                'domain' => '', // Host-only
                'secure' => $cookieParams['secure'],
                'httponly' => $cookieParams['httponly'],
                'samesite' => 'Lax'
            ]);
            error_log('[USER LOGIN] 重定向前强制设置 Cookie: name=' . $finalCookieName . ', session_id=' . substr($finalCookieCheck, 0, 16) . '..., cookie_value=' . substr($finalCookieValue, 0, 16) . '...');
        }
        
        // 验证 Redis 中 session 是否存在
        if ($finalCookieCheck && extension_loaded('redis') && defined('SESSION_REDIS_HOST')) {
            try {
                $verifyR = new Redis();
                if ($verifyR->connect(SESSION_REDIS_HOST, defined('SESSION_REDIS_PORT') ? SESSION_REDIS_PORT : 6379, 1)) {
                    if (defined('SESSION_REDIS_AUTH') && SESSION_REDIS_AUTH !== '') {
                        @$verifyR->auth(SESSION_REDIS_AUTH);
                    }
                    $phpPrefix = defined('SESSION_REDIS_PREFIX') ? SESSION_REDIS_PREFIX : 'PHPREDIS_SESSION:';
                    $phpKey = $phpPrefix . $finalCookieCheck;
                    $bakPrefix = defined('SESSION_BACKUP_REDIS_PREFIX') ? SESSION_BACKUP_REDIS_PREFIX : 'GGAI_SESSION_BAK:';
                    $bakKey = $bakPrefix . $finalCookieCheck;
                    $phpExists = $verifyR->exists($phpKey);
                    $bakExists = $verifyR->exists($bakKey);
                    $verifyR->close();
                    error_log("[USER LOGIN] 重定向前验证: session_id=" . substr($finalCookieCheck, 0, 16) . "..., php_key_exists=" . ($phpExists ? 1 : 0) . ", bak_key_exists=" . ($bakExists ? 1 : 0));
                }
            } catch (Exception $e) {
                error_log("[USER LOGIN] 重定向前验证异常: " . $e->getMessage());
            }
        }
        
        // 记录重定向前的状态
        $afterLogin = isset($_POST['login_return']) ? ggai_sanitize_login_return_path((string) $_POST['login_return']) : '';
        $xffHost = isset($_SERVER['HTTP_X_FORWARDED_HOST']) ? (string) $_SERVER['HTTP_X_FORWARDED_HOST'] : '';
        if ($xffHost !== '' && strpos($xffHost, ',') !== false) {
            $xffHost = trim(explode(',', $xffHost, 2)[0]);
        }
        error_log('[USER LOGIN] 准备重定向: session_id=' . substr($finalCookieCheck, 0, 16) . '..., cookie_name=' . $finalCookieName . ', cookie_value=' . substr($finalCookieValue, 0, 16) . '..., after_login=' . ($afterLogin !== '' ? $afterLogin : '/user/') . ', HTTP_HOST=' . ($_SERVER['HTTP_HOST'] ?? 'none') . ', X_FORWARDED_HOST=' . ($xffHost !== '' ? $xffHost : 'none'));

        // 必须用相对路径回跳：www/合伙人域反代时 HTTP_HOST 常为 web.ggai365.com，
        // 若拼绝对 URL 会把手机浏览器踢到 web.*，部分网络 DNS 解析失败（错误码-379）。
        $redirectUrl = ($afterLogin !== '') ? $afterLogin : '/user/';
        
        // 输出跳转信息（用于调试）
        if (isset($_GET['debug'])) {
            echo '<pre style="background: #000; color: #0f0; padding: 20px; font-family: monospace;">';
            echo "✓ 登录成功！\n";
            echo "SESSION ID: " . session_id() . "\n";
            echo "SESSION user_id: " . ($_SESSION['user_id'] ?? 'not_set') . "\n";
            echo "SESSION username: " . ($_SESSION['username'] ?? 'not_set') . "\n";
            echo "Cookie域名: " . $cookieDomain . "\n";
            echo "跳转URL: " . $redirectUrl . "\n";
            echo "登录耗时: " . $loginDuration . " 毫秒\n";
            echo "</pre>";
            echo '<script>setTimeout(function(){ window.location.href = "' . htmlspecialchars($redirectUrl) . '"; }, 2000);</script>';
            exit;
        }
        
        // 正常跳转
        header('Location: ' . $redirectUrl);
        exit;

        login_post_end_label:
        // 密码已通过、等待邮箱验证码时落到此标签（不建立登录会话）
        
    } catch (Exception $e) {
        $errorMessage = $e->getMessage();
        $errorTrace = $e->getTraceAsString();
        $loginDuration = isset($loginStartTime) ? round((microtime(true) - $loginStartTime) * 1000, 2) : 0;
        
        // 判断是否为敏感错误（系统内部错误，不应直接显示给用户）
        $isSensitiveError = false;
        $sensitiveKeywords = [
            '数据库查询异常',
            '数据库连接',
            'SESSION保存失败',
            'Redis',
            'PDOException',
            'SQLSTATE',
            'Connection',
            'Timeout',
            'socket',
            'file_put_contents',
            'mkdir',
            'permission denied'
        ];
        
        foreach ($sensitiveKeywords as $keyword) {
            if (stripos($errorMessage, $keyword) !== false || stripos($errorTrace, $keyword) !== false) {
                $isSensitiveError = true;
                break;
            }
        }
        
        // 记录完整错误信息到日志（包含敏感信息）
        logLoginAttempt('FAILED', '登录失败：' . $errorMessage, [
            'username' => $username ?? 'unknown',
            'error' => $errorMessage,
            'error_trace' => $errorTrace,
            'duration_ms' => $loginDuration,
            'is_sensitive' => $isSensitiveError
        ]);
        
        // 根据错误类型决定显示给用户的信息
        if ($isSensitiveError) {
            // 敏感错误：只显示通用错误信息，详细错误记录到日志
            $error = '系统错误，请稍后再试。如问题持续，请联系客服。';
            // 如果是debug模式，显示详细错误
            if (isset($_GET['debug'])) {
                $error = $errorMessage . "\n" . $errorTrace;
            }
        } else {
            // 非敏感错误：直接显示给用户（用户名不存在、密码错误等）
            $error = $errorMessage;
        }
        
        // 同时记录到error_log.txt（包含完整信息）
        error_log('[LOGIN ERROR] ' . date('Y-m-d H:i:s') . ': ' . $errorMessage . ' ' . $errorTrace);
    }
}

// 登录失败后表单仍携带回跳地址（隐藏域）
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['login_return'])) {
    $ggaiLoginReturn = ggai_sanitize_login_return_path((string) $_POST['login_return']);
}

// 只有在没有POST请求或登录失败时才包含头部
if ($_SERVER['REQUEST_METHOD'] !== 'POST' || !empty($error)) {
    include __DIR__ . '/templates/header.php';
}

// 添加注册成功提示
if (isset($_GET['reg'])): ?>
    <div style="color:green;font-weight:bold; text-align:center; margin-top:20px;"><?php echo __t('auth_register_success', '注册成功，请登录！'); ?></div>
<?php endif; ?>

<?php if (isset($_GET['cleared'])): ?>
    <div style="color:#4facfe;font-weight:bold; text-align:center; margin-top:20px; padding:15px; background:rgba(79, 172, 254, 0.1); border-radius:8px;">
        <i class="fas fa-check-circle"></i> 浏览器缓存已清理，请重新登录
    </div>
<?php endif; ?>

<!-- 登录页面主体内容 -->
<div class="login-page-wrapper">
    <!-- 装饰性动画元素 -->
    <div class="cyber-lines"></div>
    
    <div class="login-container">
        <div class="login-box">
            <div class="login-header">
                <div class="cyber-badge"></div>
                <h2 class="login-title"><?php echo __t('auth_login_heading', '用户登录'); ?></h2>
                <div class="cyber-badge"></div>
            </div>
            
            <?php if (!empty($error)): ?>
            <div class="alert" id="login-error-alert" style="background: rgba(255, 71, 87, 0.2); border-left: 4px solid #ff4757; color: #ff6b81; padding: 15px; margin-bottom: 20px; border-radius: 8px;">
                <i class="fas fa-exclamation-triangle"></i> <strong>登录失败：</strong><?php echo htmlspecialchars($error, ENT_QUOTES, 'UTF-8'); ?>
            </div>
            <script>
            // 自动弹出错误提示（非敏感错误）
            (function() {
                var errorMsg = <?php echo json_encode($error, JSON_UNESCAPED_UNICODE); ?>;
                // 敏感错误不弹窗，只在页面显示
                var sensitiveKeywords = ['系统错误', '请联系客服', '稍后再试'];
                var isSensitive = false;
                for (var i = 0; i < sensitiveKeywords.length; i++) {
                    if (errorMsg.indexOf(sensitiveKeywords[i]) !== -1) {
                        isSensitive = true;
                        break;
                    }
                }
                // 非敏感错误（用户名不存在、密码错误等）弹窗提示
                if (!isSensitive && errorMsg) {
                    setTimeout(function() {
                        alert('登录失败：' + errorMsg);
                    }, 100);
                }
            })();
            </script>
            <?php endif; ?>
            
            <?php 
            // redirected=1：会员区未登录跳转而来，不再显示「SESSION 异常」类提示（易误解）；直接展示登录表单即可。
            // 需要排查时在 URL 加 &debug=1 看下方 DEBUG 区块（且需 DEBUG=true）。
            if (isset($_GET['redirected']) && empty($error) && isset($_GET['debug']) && defined('DEBUG') && DEBUG): ?>
            <div class="alert" style="background: rgba(79, 172, 254, 0.12); border-left: 4px solid #4facfe; color: #9ecbff; padding: 12px 15px; margin-bottom: 20px; border-radius: 8px; font-size: 0.9rem;">
                <i class="fas fa-info-circle"></i> 调试：由会员区重定向而来（redirected=1）。SESSION ID: <?php echo htmlspecialchars(session_id() ?: '', ENT_QUOTES, 'UTF-8'); ?>，user_id: <?php echo htmlspecialchars(isset($_SESSION['user_id']) ? (string)$_SESSION['user_id'] : 'not_set', ENT_QUOTES, 'UTF-8'); ?>
            </div>
            <?php endif; ?>

            <?php if (isset($_GET['expired'])): ?>
            <div class="alert" style="background: rgba(255, 193, 7, 0.2); border-left-color: #ffc107; color: #ffc107;">
                <i class="fas fa-clock"></i> 登录已过期，请重新登录
            </div>
            <?php endif; ?>

<div class="alert" id="login-wait-alert" style="display:none; background: rgba(79, 172, 254, 0.18); border-left: 4px solid #4facfe; color: #9fd3ff; padding: 15px; margin-bottom: 20px; border-radius: 8px;">
    <i class="fas fa-spinner fa-spin"></i> <strong>处理中：</strong><span id="login-wait-text">系统正在处理中，请稍候...</span>
</div>
            
            <?php if (isset($_GET['debug']) && defined('DEBUG') && DEBUG): ?>
            <div style="background: rgba(79, 172, 254, 0.1); padding: 15px; border-radius: 8px; margin-bottom: 20px; font-size: 0.85rem; color: #9ecbff;">
                <strong>调试信息：</strong><br>
                Session ID: <?php echo session_id(); ?><br>
                Session状态: <?php echo session_status() === PHP_SESSION_ACTIVE ? '已启动' : '未启动'; ?><br>
                Cookie域名: <?php echo ini_get('session.cookie_domain'); ?><br>
                Session保存路径: <?php echo ini_get('session.save_path'); ?><br>
                Session处理器: <?php echo ini_get('session.save_handler'); ?><br>
                <?php if (isset($_SESSION['user_id'])): ?>
                <span style="color: #ff4757;">警告：检测到已登录状态，但仍在登录页</span>
                <?php endif; ?>
            </div>
            <?php endif; ?>
            
            <?php if (isset($_GET['logout'])): ?>
            <script>
            // 退出登录时，清除localStorage
            (function(){
                if(typeof(Storage) !== "undefined") {
                    try {
                        localStorage.removeItem("user_login_token");
                        localStorage.removeItem("user_id");
                        localStorage.removeItem("user_login_time");
                        localStorage.removeItem("user_token_expiry");
                        console.log("已清除localStorage登录信息");
                    } catch(e) {
                        console.error("清除localStorage失败:", e);
                    }
                }
            })();
            </script>
            <?php endif; ?>
            
            <form method="post" id="loginForm" class="needs-validation" novalidate action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']); ?>">
                <?php if ($ggaiLoginReturn !== ''): ?>
                <input type="hidden" name="login_return" value="<?php echo htmlspecialchars($ggaiLoginReturn, ENT_QUOTES, 'UTF-8'); ?>">
                <?php endif; ?>
                <div class="form-group">
                    <div class="input-wrapper">
                        <label class="cyber-label" for="username"><?php echo __t('auth_label_username', '用户名/邮箱/手机'); ?></label>
                        <input id="username" type="text" class="cyber-input no-icon" name="username" required
                               autocomplete="username"
                               inputmode="text"
                               autocapitalize="off"
                               autocorrect="off"
                               spellcheck="false"
                               value="<?php echo isset($_POST['username']) ? htmlspecialchars($_POST['username']) : ''; ?>">
                        <div class="input-line"></div>
                    </div>
                </div>
                
                <div class="form-group">
                    <div class="input-wrapper">
                        <label class="cyber-label" for="password"><?php echo __t('auth_label_password_with_key', '登录密码/财富钥匙'); ?></label>
                        <input id="password" type="password" class="cyber-input no-icon" name="password" required
                               autocomplete="current-password"
                               inputmode="text"
                               autocapitalize="off"
                               autocorrect="off"
                               spellcheck="false">
                        <div class="input-line"></div>
                    </div>
                </div>

                <?php if (!empty($loginOtpEnabled)): ?>
                <div class="form-group">
                    <div class="input-wrapper">
                        <label class="cyber-label" for="login_otp_code">邮箱验证码</label>
                        <div style="display:flex;gap:8px;align-items:center;">
                            <input id="login_otp_code" type="text" class="cyber-input no-icon" name="login_otp_code" required
                                   inputmode="numeric" autocomplete="one-time-code" maxlength="6" pattern="[0-9]{6}"
                                   placeholder="6 位数字" style="flex:1;">
                            <button type="button" id="sendLoginOtpBtn" class="cyber-button" style="background:transparent;border:1px solid #00f2fe55;color:#9fd3ff;padding:8px 12px;font-size:0.9em;width:auto;white-space:nowrap;">
                                发送验证码
                            </button>
                        </div>
                        <div class="input-line"></div>
                    </div>
                    <div style="color:#9ecbff;font-size:0.85em;margin-top:6px;opacity:0.85;">先填账号和密码，再点发送；验证码发到绑定邮箱。重发后请用最新一封邮件中的码。</div>
                </div>
                <script>
                (function(){
                    var sendBtn = document.getElementById('sendLoginOtpBtn');
                    if (!sendBtn) return;
                    var coolTimer = null;
                    var defaultLabel = '发送验证码';
                    function startCooldown(sec){
                        var left = Math.max(1, parseInt(sec, 10) || 60);
                        if (coolTimer) { clearInterval(coolTimer); coolTimer = null; }
                        sendBtn.disabled = true;
                        sendBtn.textContent = left + 's';
                        coolTimer = setInterval(function(){
                            left -= 1;
                            if (left <= 0) {
                                clearInterval(coolTimer);
                                coolTimer = null;
                                sendBtn.disabled = false;
                                sendBtn.textContent = defaultLabel;
                                return;
                            }
                            sendBtn.textContent = left + 's';
                        }, 1000);
                    }
                    sendBtn.addEventListener('click', function(){
                        if (sendBtn.disabled) return;
                        var u = (document.getElementById('username') || {}).value || '';
                        var p = (document.getElementById('password') || {}).value || '';
                        if (!String(u).trim() || !String(p).trim()) {
                            alert('请先填写账号和密码');
                            return;
                        }
                        var fd = new FormData();
                        fd.append('send_login_otp', '1');
                        fd.append('username', u);
                        fd.append('password', p);
                        sendBtn.disabled = true;
                        fetch(location.href, { method: 'POST', body: fd, credentials: 'same-origin' })
                            .then(function(r){ return r.json(); })
                            .then(function(j){
                                if (j && j.success) {
                                    startCooldown(j.wait || 60);
                                    return;
                                }
                                sendBtn.disabled = false;
                                sendBtn.textContent = defaultLabel;
                                alert((j && j.msg) ? j.msg : '发送失败');
                            })
                            .catch(function(){
                                sendBtn.disabled = false;
                                sendBtn.textContent = defaultLabel;
                                alert('发送失败');
                            });
                    });
                })();
                </script>
                <?php endif; ?>
                
                <button type="submit" class="cyber-button" id="loginBtn">
                    <span class="button-content">
                        <i class="fas fa-sign-in-alt"></i>
                        <?php echo __t('auth_btn_login', '登录'); ?>
                    </span>
                </button>
                
                <script>
                // 移动端兼容性：确保表单能正常提交
                (function(){
                    var form = document.getElementById('loginForm');
                    var loginBtn = document.getElementById('loginBtn');
                    var waitAlert = document.getElementById('login-wait-alert');
                    var waitText = document.getElementById('login-wait-text');
                    var isSubmitting = false;

                    function showWaitStatus(message){
                        if(waitAlert){
                            if(waitText){
                                waitText.textContent = message;
                            }
                            waitAlert.style.display = 'block';
                        }
                    }
                    
                    if(form && loginBtn){
                        // 防止重复提交
                        form.addEventListener('submit', function(e){
                            if(isSubmitting){
                                e.preventDefault();
                                return false;
                            }
                            isSubmitting = true;
                            var submitStartTime = Date.now();
                            loginBtn.disabled = true;
                            loginBtn.style.opacity = '0.6';
                            loginBtn.querySelector('.button-content').innerHTML = '<i class="fas fa-spinner fa-spin"></i> 登录中...';
                            
                            // 设置等待提示（主库波动时后端可能在自动重试，避免用户误以为是普通网络超时）
                            var timeoutId = setTimeout(function() {
                                if (isSubmitting) {
                                    console.warn('登录请求仍在等待主库恢复，继续保持提交状态');
                                    loginBtn.querySelector('.button-content').innerHTML = '<i class="fas fa-spinner fa-spin"></i> 正在重试主库，请稍候...';
                                    showWaitStatus('登录请求仍在处理中，系统正在自动重试主数据库连接，请不要重复点击。');
                                }
                            }, 30000);
                            
                            // 页面卸载时清除超时（如果跳转成功）
                            window.addEventListener('beforeunload', function() {
                                clearTimeout(timeoutId);
                            }, {once: true});
                            
                            return true;
                        });
                        
                        // 移动端：确保按钮点击能触发表单提交
                        loginBtn.addEventListener('click', function(e){
                            // 如果表单验证失败，阻止提交
                            if(!form.checkValidity()){
                                form.reportValidity();
                                e.preventDefault();
                                return false;
                            }
                        }, false);
                        
                        // 移动端：触摸事件支持
                        loginBtn.addEventListener('touchend', function(e){
                            e.preventDefault();
                            if(!isSubmitting && form.checkValidity()){
                                form.submit();
                            }
                        }, false);
                    }
                })();
                </script>
                
                <div class="login-links">
                    <a href="register.php" class="cyber-link">
                        <i class="fas fa-user-plus"></i> <?php echo __t('auth_link_no_account', '注册财富账号'); ?>
                    </a>
                    <span class="divider"></span>
                    <a href="reset_password.php" class="cyber-link">
                        <i class="fas fa-key"></i> <?php echo __t('auth_link_forgot', '找回密码'); ?>
                    </a>
                </div>
                
                <div style="margin-top: 25px; text-align: center; padding-top: 20px; border-top: 1px solid rgba(79, 172, 254, 0.2);">
                    <button type="button" id="clearCacheBtn" style="
                        background: rgba(255, 71, 87, 0.1);
                        border: 1px solid rgba(255, 71, 87, 0.3);
                        color: #ff6b81;
                        cursor: pointer;
                        padding: 12px 24px;
                        border-radius: 8px;
                        font-size: 0.9rem;
                        transition: all 0.3s ease;
                        display: inline-flex;
                        align-items: center;
                        gap: 8px;
                    ">
                        <i class="fas fa-trash-alt"></i> 清理浏览器缓存
                    </button>
                    <div style="margin-top: 10px; font-size: 0.8rem; color: #9ecbff; opacity: 0.7;">
                        如果登录后自动跳回，请点击此按钮清理缓存
                    </div>
                </div>
            </form>
            
            <script>
            // 清理浏览器缓存功能
            var clearCacheBtnEl = document.getElementById('clearCacheBtn');
            if (clearCacheBtnEl) clearCacheBtnEl.addEventListener('click', function() {
                var btn = this;
                btn.disabled = true;
                btn.style.opacity = '0.6';
                btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 正在清理...';
                
                if (confirm('确定要清理浏览器缓存吗？\n\n这将清除：\n- 所有Cookie\n- LocalStorage数据\n- SessionStorage数据\n- IndexedDB数据\n\n清理后页面将自动刷新，请重新登录。')) {
                    try {
                        // 清理LocalStorage
                        localStorage.clear();
                        console.log('✓ LocalStorage已清理');
                        
                        // 清理SessionStorage
                        sessionStorage.clear();
                        console.log('✓ SessionStorage已清理');
                        
                        // 清理IndexedDB（如果存在）
                        if ('indexedDB' in window) {
                            indexedDB.databases().then(databases => {
                                databases.forEach(db => {
                                    indexedDB.deleteDatabase(db.name);
                                });
                                console.log('✓ IndexedDB已清理');
                            }).catch(function(e) {
                                console.warn('IndexedDB清理失败:', e);
                            });
                        }
                        
                        // 清理Cookie（通过设置过期时间）
                        var cookies = document.cookie.split(";");
                        cookies.forEach(function(c) {
                            var cookieName = c.split("=")[0].trim();
                            if (cookieName) {
                                // 清理当前路径的Cookie
                                document.cookie = cookieName + "=;expires=" + new Date(0).toUTCString() + ";path=/";
                                // 清理根路径的Cookie
                                document.cookie = cookieName + "=;expires=" + new Date(0).toUTCString() + ";path=/;domain=" + window.location.hostname;
                                // 清理带域名的Cookie
                                var domain = window.location.hostname;
                                var domainParts = domain.split('.');
                                if (domainParts.length >= 2) {
                                    var rootDomain = '.' + domainParts.slice(-2).join('.');
                                    document.cookie = cookieName + "=;expires=" + new Date(0).toUTCString() + ";path=/;domain=" + rootDomain;
                                }
                            }
                        });
                        console.log('✓ Cookie已清理');
                        
                        // 延迟一下再刷新，确保清理完成
                        setTimeout(function() {
                            alert('缓存已清理完成！\n\n页面将自动刷新，请重新登录。');
                            window.location.href = 'login.php?logout=1&cleared=1';
                        }, 500);
                    } catch (e) {
                        alert('清理缓存时出错：' + e.message + '\n\n请手动清理浏览器缓存或使用无痕模式登录。');
                        console.error('清理缓存错误：', e);
                        btn.disabled = false;
                        btn.style.opacity = '1';
                        btn.innerHTML = '<i class="fas fa-trash-alt"></i> 清理浏览器缓存';
                    }
                } else {
                    btn.disabled = false;
                    btn.style.opacity = '1';
                    btn.innerHTML = '<i class="fas fa-trash-alt"></i> 清理浏览器缓存';
                }
            });
            
            // 鼠标悬停效果
            document.getElementById('clearCacheBtn').addEventListener('mouseenter', function() {
                if (!this.disabled) {
                    this.style.background = 'rgba(255, 71, 87, 0.2)';
                    this.style.borderColor = 'rgba(255, 71, 87, 0.5)';
                }
            });
            document.getElementById('clearCacheBtn').addEventListener('mouseleave', function() {
                if (!this.disabled) {
                    this.style.background = 'rgba(255, 71, 87, 0.1)';
                    this.style.borderColor = 'rgba(255, 71, 87, 0.3)';
                }
            });
            </script>
        </div>
    </div>
</div>

<style>
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
.login-page-wrapper {
    min-height: calc(100vh - 160px);
    position: relative;
    background: linear-gradient(135deg, #0a192f 0%, #20232a 100%);
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 40px 0;
}

/* 赛博朋克风格线条动画 */
.cyber-lines {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: 
        linear-gradient(90deg, rgba(0,255,255,0.1) 1px, transparent 1px) 0 0 / 50px 50px,
        linear-gradient(rgba(0,255,255,0.1) 1px, transparent 1px) 0 0 / 50px 50px;
    animation: moveLines 20s linear infinite;
}

@keyframes moveLines {
    0% { transform: translate(0, 0); }
    100% { transform: translate(50px, 50px); }
}

.login-container {
    position: relative;
    z-index: 1;
    width: 100%;
    max-width: 420px;
    margin: 0 20px;
}

.login-box {
    background: rgba(16, 24, 39, 0.8);
    backdrop-filter: blur(10px);
    border-radius: 15px;
    padding: 40px;
    box-shadow: 0 0 30px rgba(0, 255, 255, 0.1),
                inset 0 0 15px rgba(0, 255, 255, 0.05);
    border: 1px solid rgba(0, 255, 255, 0.1);
    animation: glowPulse 3s infinite;
}

@keyframes glowPulse {
    0% { box-shadow: 0 0 30px rgba(0, 255, 255, 0.1); }
    50% { box-shadow: 0 0 40px rgba(0, 255, 255, 0.2); }
    100% { box-shadow: 0 0 30px rgba(0, 255, 255, 0.1); }
}

.login-header {
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 30px;
    gap: 20px;
}

.cyber-badge {
    width: 30px;
    height: 3px;
    background: linear-gradient(90deg, #00f2fe, #4facfe);
    position: relative;
}

.cyber-badge::before,
.cyber-badge::after {
    content: '';
    position: absolute;
    width: 6px;
    height: 6px;
    background: #4facfe;
    top: -1.5px;
    border-radius: 50%;
}

.cyber-badge::before { left: -3px; }
.cyber-badge::after { right: -3px; }

.login-title {
    color: #fff;
    font-size: 1.8rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 2px;
    margin: 0;
    text-shadow: 0 0 10px rgba(79, 172, 254, 0.5);
}

.input-wrapper {
    position: relative;
    margin-bottom: 25px;
}

.cyber-label {
    display: flex;
    align-items: center;
    gap: 8px;
    color: #9ecbff;
    font-weight: 600;
    margin-bottom: 8px;
    font-size: 0.95rem;
}

/* 登录表单不再使用图标，隐藏任何潜在残留 */
.input-wrapper i { display:none !important; }

.cyber-input {
    width: 100%;
    padding: 14px 14px; /* 两行布局后不再需要给图标让位 */
    background: rgba(16, 24, 39, 0.6);
    border: 1px solid rgba(79, 172, 254, 0.2);
    border-radius: 8px;
    color: #fff;
    font-size: 1rem;
    transition: all 0.3s ease;
    box-sizing: border-box;
    -webkit-appearance: none; /* 移除iOS默认样式 */
    -moz-appearance: none;
    appearance: none;
    -webkit-tap-highlight-color: transparent; /* 移除移动端点击高亮 */
    touch-action: manipulation; /* 优化触摸响应 */
}

/* 无内嵌图标版本（两行布局） */
.cyber-input.no-icon { padding: 14px 14px; }

.cyber-input:focus {
    outline: none;
    border-color: #4facfe;
    box-shadow: 0 0 15px rgba(79, 172, 254, 0.3);
}

.input-line {
    position: absolute;
    bottom: 0;
    left: 0;
    height: 2px;
    width: 0;
    background: linear-gradient(90deg, #00f2fe, #4facfe);
    transition: width 0.3s ease;
}

.cyber-input:focus + .input-line {
    width: 100%;
}

.cyber-button {
    width: 100%;
    padding: 15px;
    background: linear-gradient(45deg, #00f2fe, #4facfe);
    border: none;
    border-radius: 8px;
    color: #fff;
    font-size: 1.1rem;
    font-weight: 600;
    letter-spacing: 1px;
    cursor: pointer;
    transition: all 0.3s ease;
    position: relative;
    overflow: hidden;
    -webkit-tap-highlight-color: transparent; /* 移除移动端点击高亮 */
    touch-action: manipulation; /* 优化触摸响应 */
    user-select: none; /* 防止文本选择 */
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
}

.cyber-button::before {
    content: '';
    position: absolute;
    top: -50%;
    left: -50%;
    width: 200%;
    height: 200%;
    background: linear-gradient(45deg, transparent, rgba(255,255,255,0.2), transparent);
    transform: rotate(45deg);
    animation: buttonShine 2s infinite;
}

@keyframes buttonShine {
    0% { transform: rotate(45deg) translateX(-200%); }
    100% { transform: rotate(45deg) translateX(200%); }
}

.cyber-button:hover {
    transform: translateY(-2px);
    box-shadow: 0 5px 15px rgba(79, 172, 254, 0.4);
}

.login-links {
    margin-top: 25px;
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 20px;
}

.cyber-link {
    color: #4facfe;
    text-decoration: none;
    font-size: 0.9rem;
    transition: all 0.3s ease;
    position: relative;
}

.cyber-link:hover {
    color: #00f2fe;
    text-shadow: 0 0 10px rgba(79, 172, 254, 0.5);
}

.divider {
    width: 2px;
    height: 15px;
    background: linear-gradient(to bottom, #00f2fe, #4facfe);
    border-radius: 1px;
}

.alert {
    background: rgba(255, 71, 87, 0.2);
    border-left: 4px solid #ff4757;
    color: #ff6b81;
    padding: 15px;
    border-radius: 8px;
    margin-bottom: 25px;
    font-size: 0.9rem;
    display: flex;
    align-items: center;
    gap: 10px;
}

@media (max-width: 480px) {
    .login-box {
        padding: 30px 20px;
    }
    
    .login-title {
        font-size: 1.5rem;
    }
    
    .cyber-badge {
        width: 20px;
    }
}

/* 移动端统一适配 - 处理所有浏览器差异 */
@media (max-width: 768px) {
    /* 防止移动端缩放导致的问题 */
    html {
        -webkit-text-size-adjust: 100%;
        -ms-text-size-adjust: 100%;
        text-size-adjust: 100%;
    }
    
    body {
        -webkit-overflow-scrolling: touch; /* iOS平滑滚动 */
        overflow-x: hidden; /* 防止横向滚动 */
    }
    
    .login-page-wrapper {
        padding: 15px 0;
        min-height: 100vh;
        min-height: -webkit-fill-available; /* iOS Safari全屏支持 */
        display: flex;
        align-items: center;
        justify-content: center;
        position: relative;
    }
    .login-container {
        margin: 0 16px;
        max-width: 100%;
        width: 100%;
    }
    .login-box {
        padding: 36px 28px; /* 华为浏览器整体偏小，增大内边距与视觉体量 */
        border-radius: 15px;
        width: 100%;
        box-sizing: border-box;
    }
    .login-title {
        font-size: 2rem; /* 提升标题尺寸 */
        letter-spacing: 1px;
        margin-bottom: 30px;
    }
    .cyber-badge {
        width: 30px;
        height: 3px;
    }
    .input-wrapper {
        margin-bottom: 25px;
    }
    .cyber-label { font-size: 1.05rem; margin-bottom: 10px; }
    .cyber-input {
        padding: 20px 18px; /* 提高可点击高度 */
        font-size: 18px; /* 统一字体大小，防止缩放 */
        border-radius: 12px;
        width: 100%;
        box-sizing: border-box;
        border: 2px solid rgba(79, 172, 254, 0.3);
    }
    .cyber-input:focus {
        border-color: #4facfe;
        box-shadow: 0 0 25px rgba(79, 172, 254, 0.4);
    }
    .cyber-button {
        padding: 20px;
        font-size: 1.35rem; /* 按钮文字更醒目 */
        border-radius: 12px;
        width: 100%;
        margin-top: 15px;
    }
    .login-links {
        gap: 15px;
        font-size: 1.1rem;
        flex-direction: column;
        align-items: center;
        margin-top: 25px;
    }
    .login-links .divider {
        display: none;
    }
    .cyber-link {
        padding: 15px 25px;
        margin: 8px 0;
        font-size: 1.1rem;
        border-radius: 10px;
        background: rgba(79, 172, 254, 0.1);
        border: 2px solid rgba(79, 172, 254, 0.3);
        width: 100%;
        text-align: center;
        box-sizing: border-box;
    }
}

@media (max-width: 600px) {
    .login-page-wrapper {
        padding: 10px 0;
        min-height: 100vh;
    }
    .login-container {
        margin: 0 12px;
        max-width: 100%;
    }
    .login-box {
        padding: 30px 22px;
        border-radius: 12px;
    }
    .login-title {
        font-size: 1.9rem;
    }
    .input-wrapper {
        margin-bottom: 20px;
    }
    .cyber-input {
        padding: 18px 16px;
        font-size: 18px; /* 避免过小 */
        box-sizing: border-box;
    }
    .cyber-button {
        padding: 20px;
        font-size: 1.3rem;
    }
    .login-links {
        gap: 12px;
        font-size: 1rem;
    }
}
</style>

<?php include __DIR__ . '/templates/footer.php'; ?> 