<?php
require_once __DIR__ . '/config/database.php';
require_once __DIR__ . '/admin/includes/database.php';

$db = Database::getInstance();

// ========== 确保卡密/手机号管理所需字段存在（含 is_enabled 启用状态） ==========
require_once __DIR__ . '/admin/includes/migrate.php';
require_once __DIR__ . '/admin/includes/settings_helper.php';
ensureCardSchema($db);

// ========== 获取系统设置 ==========
$styleTemplate = 'default';
$pageTitle = '腾讯视频';
$pageIcon = 'https://tse1-mm.cn.bing.net/th/id/OIP-C.XYR-ifbzUewZ--WCOwvNSQAAAA?w=167&h=180&c=7&r=0&o=7&dpr=1.1&pid=1.7&rm=3';
$tutorialImage = '/img/jc.png';
$tutorialText = "1.复制手机号，到 APP 【选手机号登录】区号改+1\n\n2.验证码发送后回到本页面，刷新等待验证码出现。\n\n3.复制验证码并粘贴到 APP，完成登录。\n\n4.长时间不显示验证码，返回 app 在获取一次";

// ========== 违禁词（按卡密归属用户从数据库加载，见页面加载后） ==========
$forbiddenWords = [];

// 被拉黑 IP 拦截页
function blockAccess($ip) {
    header('HTTP/1.1 403 Forbidden');
    echo '<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><title>访问受限</title>';
    echo '<style>body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"PingFang SC","Microsoft YaHei",sans-serif;background:#0f1115;color:#e2e8f0;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;}';
    echo '.box{text-align:center;padding:40px 48px;background:#1a1f2b;border:1px solid #2d3748;border-radius:16px;}';
    echo '.icon{font-size:48px;margin-bottom:12px;}.t{font-size:20px;font-weight:600;margin-bottom:8px;}.s{color:#a0aec0;font-size:14px;}.ip{margin-top:14px;font-family:monospace;color:#fc8181;background:#2d1517;padding:4px 12px;border-radius:8px;display:inline-block;}</style></head>';
    echo '<body><div class="box"><div class="icon">🚫</div><div class="t">您已被拉黑</div><div class="s">该 IP 地址已被管理员禁止访问此页面</div><div class="ip">IP: ' . htmlspecialchars($ip) . '</div></div></body></html>';
    exit;
}

// ========== 检查验证码是否包含违禁词 ==========
function hasForbiddenWord($text, $forbiddenWords) {
    if (empty($text) || empty($forbiddenWords)) {
        return false;
    }
    foreach ($forbiddenWords as $word) {
        if (stripos($text, $word) !== false) {
            return true;
        }
    }
    return false;
}

// ========== 提取文本中的第一个数字序列 ==========
function extractNumbers($text) {
    if (empty($text)) {
        return '';
    }

    if (preg_match('/\b(\d{4,6})\b/', $text, $matches)) {
        return $matches[1];
    }
    // 如果没有找到4-6位的数字，尝试提取第一个数字序列
    if (preg_match('/\d+/', $text, $matches)) {
        return $matches[0];
    }
    return $text; // 如果没有数字，返回原文本
}

// ========== 从+852 API响应中提取验证码内容 ==========
function extractHKCode($response) {
    if (empty($response)) {
        return ['code' => '', 'time' => '', 'found' => false];
    }
    
    $data = json_decode($response, true);
    if (json_last_error() === JSON_ERROR_NONE && isset($data['code'])) {
        // 检查是否有验证码 (code == 1 表示有验证码)
        if ($data['code'] == 1 && isset($data['data']['code']) && !empty($data['data']['code'])) {
            return [
                'code' => $data['data']['code'],
                'time' => $data['data']['code_time'] ?? date('Y-m-d H:i:s'),
                'found' => true
            ];
        }
        // code == 0 表示暂无验证码
        if ($data['code'] == 0) {
            return ['code' => '', 'time' => '', 'found' => false, 'noCode' => true];
        }
    }
    
    // 如果不是JSON或格式不对，尝试直接作为文本处理
    if (!empty($response) && $response !== '0|0' && strpos($response, '验证码') !== false) {
        return [
            'code' => $response,
            'time' => date('Y-m-d H:i:s'),
            'found' => true
        ];
    }
    
    return ['code' => '', 'time' => '', 'found' => false];
}

try {
    // 全局 system_settings 表已弃用，设置改为按用户隔离存储在 user_settings 表，
    // 实际样式/标题/图标/教程/违禁词在页面加载后按卡密归属用户加载（见下方）。
} catch (Exception $e) {
    // 兼容保留
}

function getPhoneDisplay($phone) {
    $cleanPhone = preg_replace('/[^0-9]/', '', $phone);
    $len = strlen($cleanPhone);
    
    // 香港号码：8位，不以1开头（+852导入的号码）
    if ($len == 8 && substr($cleanPhone, 0, 1) != '1') {
        return [
            'display' => '+852 ' . $cleanPhone,
            'flag' => '🇭🇰',
            'label' => '中国香港 +852',
            'type' => 'hk'
        ];
    }
    
    // 美国号码：10位或11位，以1开头
    if (($len == 10 || $len == 11) && substr($cleanPhone, 0, 1) == '1') {
        return [
            'display' => '+1 ' . $cleanPhone,
            'flag' => '🇺🇸',
            'label' => '美国 +1',
            'type' => 'us'
        ];
    }
    
    // 默认显示为美国
    return [
        'display' => '+1 ' . $cleanPhone,
        'flag' => '🇺🇸',
        'label' => '美国 +1',
        'type' => 'us'
    ];
}

// ========== 获取设备信息 ==========
function getDeviceInfo() {
    $ua = $_SERVER['HTTP_USER_AGENT'] ?? '';
    $info = [];
    
    // 检测操作系统
    if (strpos($ua, 'Windows') !== false) {
        $info['os'] = 'Windows';
        if (strpos($ua, 'Windows NT 10.0') !== false) $info['os'] = 'Windows 10';
        elseif (strpos($ua, 'Windows NT 6.1') !== false) $info['os'] = 'Windows 7';
        elseif (strpos($ua, 'Windows NT 6.2') !== false) $info['os'] = 'Windows 8';
        elseif (strpos($ua, 'Windows NT 6.3') !== false) $info['os'] = 'Windows 8.1';
    } elseif (strpos($ua, 'Mac OS X') !== false) {
        $info['os'] = 'macOS';
    } elseif (strpos($ua, 'Linux') !== false) {
        $info['os'] = 'Linux';
    } elseif (strpos($ua, 'Android') !== false) {
        $info['os'] = 'Android';
    } elseif (strpos($ua, 'iPhone') !== false || strpos($ua, 'iPad') !== false) {
        $info['os'] = 'iOS';
    } else {
        $info['os'] = 'Unknown';
    }
    
    // 检测浏览器
    if (strpos($ua, 'Chrome') !== false && strpos($ua, 'Edg') === false && strpos($ua, 'OPR') === false) {
        $info['browser'] = 'Chrome';
    } elseif (strpos($ua, 'Firefox') !== false) {
        $info['browser'] = 'Firefox';
    } elseif (strpos($ua, 'Safari') !== false && strpos($ua, 'Chrome') === false) {
        $info['browser'] = 'Safari';
    } elseif (strpos($ua, 'Edg') !== false) {
        $info['browser'] = 'Edge';
    } elseif (strpos($ua, 'OPR') !== false || strpos($ua, 'Opera') !== false) {
        $info['browser'] = 'Opera';
    } elseif (strpos($ua, 'MSIE') !== false || strpos($ua, 'Trident') !== false) {
        $info['browser'] = 'IE';
    } else {
        $info['browser'] = 'Other';
    }
    
    // 检测设备类型
    if (strpos($ua, 'Mobile') !== false || strpos($ua, 'Android') !== false || strpos($ua, 'iPhone') !== false) {
        $info['device'] = ' Mobile';
    } elseif (strpos($ua, 'iPad') !== false) {
        $info['device'] = ' Tablet';
    } else {
        $info['device'] = ' Desktop';
    }
    
    return $info['device'] . ' | ' . $info['os'] . ' | ' . $info['browser'];
}

// 获取页面代码
$pageCode = '';

// 1. 从 GET 参数获取
if (isset($_GET['code'])) {
    $pageCode = $_GET['code'];
} 
// 2. 从 PATH_INFO 获取 (如 /abc123)
elseif (isset($_SERVER['PATH_INFO'])) {
    $pathInfo = trim($_SERVER['PATH_INFO'], '/');
    $parts = explode('/', $pathInfo);
    $pageCode = $parts[0] ?? '';
}
// 3. 从 URL 路径中提取 (如 /abc123)
else {
    $requestUri = $_SERVER['REQUEST_URI'];
    $scriptName = $_SERVER['SCRIPT_NAME'];
    
    if (strpos($requestUri, $scriptName) === 0) {
        $relativePath = substr($requestUri, strlen($scriptName));
    } else {
        $basePath = '/';
        if (strpos($requestUri, $basePath) === 0) {
            $relativePath = substr($requestUri, strlen($basePath));
        } else {
            $relativePath = $requestUri;
        }
    }
    
    if (strpos($relativePath, '?') !== false) {
        $relativePath = substr($relativePath, 0, strpos($relativePath, '?'));
    }
    
    $relativePath = ltrim($relativePath, '/');
    $parts = explode('/', $relativePath);
    $pageCode = $parts[0] ?? '';
    
    if ($pageCode === 'index.php' || empty($pageCode)) {
        if (preg_match('/\/([A-Za-z0-9]{8,12})/', $_SERVER['REQUEST_URI'], $matches)) {
            $pageCode = $matches[1];
        }
    }
}

if (empty($pageCode)) {
    $uri = $_SERVER['REQUEST_URI'];
    if (preg_match('/\?([A-Za-z0-9]{8,12})/', $uri, $matches)) {
        $pageCode = $matches[1];
    }
}

if (empty($pageCode)) {
    die('页面不存在 - 请提供有效的页面代码');
}

// ========== 查询卡密并自动激活 ==========
$page = $db->fetchOne("SELECT * FROM generated_pages WHERE page_code = ?", [$pageCode]);

if (!$page) {
    die('页面不存在或已过期~ ');
}

// ========== 按卡密归属用户加载其独立系统设置 ==========
$ownerId = $page['user_id'] ?? null;
if (empty($ownerId) && !empty($page['number_id'])) {
    $ownPhone = $db->fetchOne("SELECT user_id FROM phone_numbers WHERE id = ?", [$page['number_id']]);
    $ownerId = $ownPhone['user_id'] ?? null;
}
$pageSettings = getUserSettings($db, $ownerId ?: 0);
$styleTemplate = $pageSettings['style_template'];
$pageTitle     = $pageSettings['page_title'];
$pageIcon      = $pageSettings['page_icon'];
$tutorialImage = $pageSettings['tutorial_image'];
$tutorialText  = $pageSettings['tutorial_text'];
$forbiddenWords = $pageSettings['banned_words_arr'];

// ========== IP 黑名单拦截（按归属用户） ==========
if (!empty($pageSettings['ip_blacklist_arr'])) {
    $visitorIp = $_SERVER['REMOTE_ADDR'] ?? '';
    if ($visitorIp !== '' && in_array($visitorIp, $pageSettings['ip_blacklist_arr'], true)) {
        blockAccess($visitorIp);
    }
}

// ========== 核心修复：自动激活未激活的卡密 ==========
if ($page['status'] === 'inactive' || $page['is_active'] == 0) {
    $expireDays = $page['expire_days'] ?? 7;
    
    // ===== 关键修改：判断是否为小时卡（小数） =====
    // 如果 expire_days 是小数（如 0.0417 = 1小时），按小时计算过期时间
    if (is_float($expireDays) || ($expireDays < 1 && $expireDays > 0)) {
        // 小时卡：按小时计算
        $hours = round($expireDays * 24);
        if ($hours < 1) $hours = 1;
        $expireTime = date('Y-m-d H:i:s', strtotime("+{$hours} hours"));
    } else {
        // 天卡：按天计算
        $days = (int)$expireDays;
        if ($days < 1) $days = 1;
        $expireTime = date('Y-m-d H:i:s', strtotime("+{$days} days"));
    }
    // ===== 修改结束 =====
    
    $activatedAt = date('Y-m-d H:i:s');
    
    // 更新数据库：激活卡密。若尚未分配手机号，则按「首选分组 + 启用状态 + 最大绑定次数」自动分配
    $assignedPhone = $page['phone'] ?? '';
    $assignedNumberId = $page['number_id'] ?? null;
    $assignedApiUrl = $page['api_url'] ?? '';
    if ($assignedPhone === '' || $assignedPhone === null) {
        $groupPref = $page['group_id'] ?? null;
        $phWhere = 'is_enabled = 1';
        $phParams = [];
        if (!empty($page['user_id'])) { $phWhere .= ' AND user_id = ?'; $phParams[] = $page['user_id']; }
        if ($groupPref) { $phWhere .= ' AND group_id = ?'; $phParams[] = $groupPref; }
        try {
            $cands = $db->fetchAll("SELECT * FROM phone_numbers WHERE $phWhere", $phParams);
            if (!empty($cands)) {
                $usageRows = $db->fetchAll("SELECT number_id, COUNT(*) AS c FROM generated_pages WHERE number_id IS NOT NULL GROUP BY number_id");
                $usage = [];
                foreach ($usageRows as $r) { $usage[$r['number_id']] = (int)$r['c']; }
                shuffle($cands);
                foreach ($cands as $cp) {
                    $cap = (int)($cp['max_bind_count'] ?? 0) === 0 ? PHP_INT_MAX : (int)$cp['max_bind_count'];
                    $used = $usage[$cp['id']] ?? 0;
                    if ($used < $cap) {
                        $assignedPhone = $cp['phone'];
                        $assignedNumberId = $cp['id'];
                        $assignedApiUrl = $cp['api_url'];
                        break;
                    }
                }
            }
        } catch (Exception $e) {
            // is_enabled 字段暂不可用时，退化为不分配手机号
            $assignedPhone = ''; $assignedNumberId = null; $assignedApiUrl = '';
        }
    }
    $db->update('generated_pages', [
        'status' => 'active',
        'is_active' => 1,
        'activated_at' => $activatedAt,
        'expire_time' => $expireTime,
        'phone' => $assignedPhone,
        'number_id' => $assignedNumberId,
        'api_url' => $assignedApiUrl
    ], 'page_code = ?', [$pageCode]);
    
    // 重新查询更新后的数据
    $page = $db->fetchOne("SELECT * FROM generated_pages WHERE page_code = ?", [$pageCode]);
    
    // 记录激活事件
    $sessionId = session_id() ?: md5($_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT']);
    $db->insert('access_records', [
        'page_code' => $pageCode,
        'action_type' => 'activate',
        'ip_address' => $_SERVER['REMOTE_ADDR'] ?? '',
        'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '',
        'device_info' => getDeviceInfo(),
        'session_id' => $sessionId,
        'referer' => $_SERVER['HTTP_REFERER'] ?? '',
        'code_content' => null,
        'copied_phone' => 0,
        'copied_code' => 0,
        'created_at' => date('Y-m-d H:i:s')
    ]);
}

// 获取手机号信息
$phoneInfo = getPhoneDisplay($page['phone']);
$phoneNumberOnly = preg_replace('/[^0-9]/', '', $page['phone']);

// 检查过期
$isExpired = false;
$expireTimeFormatted = '未设置';
if ($page['is_active'] && $page['expire_time']) {
    $now = new DateTime();
    $expire = new DateTime($page['expire_time']);
    $isExpired = $now > $expire;
    
    if ($isExpired && $page['status'] !== 'expired') {
        $db->update('generated_pages', ['status' => 'expired'], 'page_code = ?', [$pageCode]);
        $page['status'] = 'expired';
    }
    
    $expireTimeFormatted = date('Y-m-d H:i:s', strtotime($page['expire_time']));
}

// ========== 获取次数配置信息 ==========
$maxAttempts = $page['max_attempts'] ?? 1;
$attemptsConfig = $page['max_attempts_config'] ?? 'default';
$customAttempts = $page['custom_attempts'] ?? null;
$usedCount = $page['used_count'] ?? 0;

// 计算剩余次数（无限次时显示为很大的数）
$isUnlimited = ($attemptsConfig === 'unlimited');
$remainingAttempts = $isUnlimited ? 9999 : max(0, $maxAttempts - $usedCount);

// 显示用的次数标签
if ($attemptsConfig === 'unlimited') {
    $attemptsLabel = '♾️ 无限次';
    $maxDisplay = '∞';
} elseif ($attemptsConfig === 'custom') {
    $attemptsLabel = $customAttempts . ' 次';
    $maxDisplay = $customAttempts;
} else {
    $attemptsLabel = '默认(1次)';
    $maxDisplay = 1;
}

$lastCode = $page['last_code'] ?? '';
$lastCodeTime = $page['last_code_time'] ?? '';
$hasValidCode = !empty($lastCode);
$showCode = (!empty($lastCode) && !$isExpired);
$isAttemptsExhausted = (!$isUnlimited && $usedCount >= $maxAttempts);

// 处理AJAX请求
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $action = $_POST['action'] ?? '';
    
    // 获取验证码
    if ($action === 'fetch_api' || $action === 'renew_code') {
        // 检查次数（无限次除外）
        if (!$isUnlimited && $usedCount >= $maxAttempts) {
            echo json_encode([
                'success' => false,
                'noAttempts' => true,
                'message' => '验证码获取次数已用完'
            ]);
            exit;
        }
        
        $url = str_replace('{phone}', $page['phone'], $page['api_url']);
        
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36');
        
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        
        if ($httpCode == 200 && !empty($response)) {
            $response = trim($response);
            
            // ============================================================
            // +852 专用处理：解析JSON格式的API响应
            // ============================================================
            if ($phoneInfo['type'] == 'hk') {
                $hkResult = extractHKCode($response);
                
                // 检查是否无验证码 (code: 0)
                if (isset($hkResult['noCode']) && $hkResult['noCode'] === true) {
                    echo json_encode([
                        'success' => false,
                        'needRetry' => true,
                        'noCode' => true,
                        'message' => '暂无验证码，继续等待...'
                    ]);
                    exit;
                }
                
                // 检查是否找到验证码
                if ($hkResult['found'] && !empty($hkResult['code'])) {
                    $displayContent = $hkResult['code'];
                    $codeTime = $hkResult['time'];
                    
                    // 检查是否包含违禁词
                    if (hasForbiddenWord($displayContent, $forbiddenWords)) {
                        echo json_encode([
                            'success' => false,
                            'needRetry' => true,
                            'forbidden' => true,
                            'message' => '验证码包含违禁词，已过滤'
                        ]);
                        exit;
                    }
                    
                    // 检查是否与当前验证码相同
                    if ($displayContent === $lastCode) {
                        echo json_encode([
                            'success' => false,
                            'needRetry' => true,
                            'sameAsCurrent' => true,
                            'message' => '与当前验证码相同，继续等待...'
                        ]);
                        exit;
                    }
                    
                    // 检查是否与其他卡密重复
                    $duplicate = $db->fetchOne(
                        "SELECT id FROM generated_pages WHERE phone = ? AND last_code = ? AND page_code != ?",
                        [$page['phone'], $displayContent, $pageCode]
                    );
                    if ($duplicate) {
                        echo json_encode([
                            'success' => false,
                            'needRetry' => true,
                            'duplicate' => true,
                            'message' => '验证码重复，继续等待...'
                        ]);
                        exit;
                    }
                    
                    // 保存验证码
                    $newUsedCount = $usedCount + 1;
                    $db->update('generated_pages', [
                        'last_code' => $displayContent,
                        'last_code_time' => $codeTime,
                        'used_count' => $newUsedCount
                    ], 'page_code = ?', [$pageCode]);
                    
                    $db->insert('access_records', [
                        'page_code' => $pageCode,
                        'ip_address' => $_SERVER['REMOTE_ADDR'] ?? '',
                        'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '',
                        'code_content' => $displayContent,
                        'created_at' => date('Y-m-d H:i:s')
                    ]);
                    
                    $remaining = $isUnlimited ? 9999 : ($maxAttempts - $newUsedCount);
                    echo json_encode([
                        'success' => true,
                        'code' => $displayContent,
                        'code_time' => $codeTime,
                        'remainingAttempts' => $remaining,
                        'usedCount' => $newUsedCount,
                        'maxAttempts' => $maxAttempts,
                        'isUnlimited' => $isUnlimited
                    ]);
                    exit;
                }
                
                // 如果响应不是预期的JSON格式，尝试直接作为文本处理
                if (!empty($response) && $response !== '0|0' && strpos($response, '验证码') !== false) {
                    // 检查是否包含违禁词
                    if (hasForbiddenWord($response, $forbiddenWords)) {
                        echo json_encode([
                            'success' => false,
                            'needRetry' => true,
                            'forbidden' => true,
                            'message' => '验证码包含违禁词，已过滤'
                        ]);
                        exit;
                    }
                    
                    if ($response === $lastCode) {
                        echo json_encode([
                            'success' => false,
                            'needRetry' => true,
                            'sameAsCurrent' => true,
                            'message' => '与当前验证码相同，继续等待...'
                        ]);
                        exit;
                    }
                    
                    $newUsedCount = $usedCount + 1;
                    $db->update('generated_pages', [
                        'last_code' => $response,
                        'last_code_time' => date('Y-m-d H:i:s'),
                        'used_count' => $newUsedCount
                    ], 'page_code = ?', [$pageCode]);
                    
                    $db->insert('access_records', [
                        'page_code' => $pageCode,
                        'ip_address' => $_SERVER['REMOTE_ADDR'] ?? '',
                        'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '',
                        'code_content' => $response,
                        'created_at' => date('Y-m-d H:i:s')
                    ]);
                    
                    $remaining = $isUnlimited ? 9999 : ($maxAttempts - $newUsedCount);
                    echo json_encode([
                        'success' => true,
                        'code' => $response,
                        'code_time' => date('Y-m-d H:i:s'),
                        'remainingAttempts' => $remaining,
                        'usedCount' => $newUsedCount,
                        'maxAttempts' => $maxAttempts,
                        'isUnlimited' => $isUnlimited
                    ]);
                    exit;
                }
                
                echo json_encode([
                    'success' => false,
                    'needRetry' => true,
                    'message' => '等待验证码...'
                ]);
                exit;
            }
            
            // ============================================================
            // +1 美国号码处理：提取数字验证码
            // ============================================================
            $data = json_decode($response, true);
            $verificationCode = '';
            $codeTime = '';
            $isValidCode = false;
            
            if (json_last_error() === JSON_ERROR_NONE && isset($data['code']) && $data['code'] == 1) {
                if (isset($data['data']['code_time'])) {
                    $codeTime = $data['data']['code_time'];
                }
                if (isset($data['data']['code'])) {
                    $codeContent = $data['data']['code'];
                    if (preg_match('/验证码(\d{4})/', $codeContent, $matches)) {
                        $verificationCode = $matches[1];
                        $isValidCode = true;
                    } elseif (preg_match('/\b(\d{4,6})\b/', $codeContent, $matches)) {
                        $verificationCode = $matches[1];
                        $isValidCode = true;
                    }
                }
            }
            
            if ($isValidCode && !empty($verificationCode)) {
                // ===== 检查验证码是否包含违禁词 =====
                if (hasForbiddenWord($verificationCode, $forbiddenWords)) {
                    echo json_encode([
                        'success' => false,
                        'needRetry' => true,
                        'forbidden' => true,
                        'message' => '验证码包含违禁词，已过滤'
                    ]);
                    exit;
                }
                
                $duplicate = $db->fetchOne(
                    "SELECT id FROM generated_pages WHERE phone = ? AND last_code = ? AND page_code != ?",
                    [$page['phone'], $verificationCode, $pageCode]
                );
                if ($duplicate) {
                    echo json_encode([
                        'success' => false,
                        'needRetry' => true,
                        'duplicate' => true,
                        'message' => '验证码重复，继续等待...'
                    ]);
                    exit;
                }
                
                $newUsedCount = $usedCount + 1;
                $db->update('generated_pages', [
                    'last_code' => $verificationCode,
                    'last_code_time' => $codeTime ?: date('Y-m-d H:i:s'),
                    'used_count' => $newUsedCount
                ], 'page_code = ?', [$pageCode]);
                
                $db->insert('access_records', [
                    'page_code' => $pageCode,
                    'ip_address' => $_SERVER['REMOTE_ADDR'] ?? '',
                    'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '',
                    'code_content' => $verificationCode,
                    'created_at' => date('Y-m-d H:i:s')
                ]);
                
                $remaining = $isUnlimited ? 9999 : ($maxAttempts - $newUsedCount);
                echo json_encode([
                    'success' => true,
                    'code' => $verificationCode,
                    'code_time' => $codeTime,
                    'remainingAttempts' => $remaining,
                    'usedCount' => $newUsedCount,
                    'maxAttempts' => $maxAttempts,
                    'isUnlimited' => $isUnlimited
                ]);
                exit;
            }
        }
        
        echo json_encode([
            'success' => false,
            'needRetry' => true,
            'message' => '等待验证码...'
        ]);
        exit;
    }
    
    // 记录复制
    if ($action === 'record_copy') {
        $type = $_POST['type'] ?? '';
        $db->insert('access_records', [
            'page_code' => $pageCode,
            'ip_address' => $_SERVER['REMOTE_ADDR'] ?? '',
            'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '',
            'copied_phone' => $type === 'phone' ? 1 : 0,
            'copied_code' => $type === 'code' ? 1 : 0,
            'created_at' => date('Y-m-d H:i:s')
        ]);
        echo json_encode(['success' => true]);
        exit;
    }
    
    echo json_encode(['success' => false]);
    exit;
}

$showFetching = (empty($lastCode) && !$isAttemptsExhausted && !$isExpired);
$canRenew = ($showCode && !$isAttemptsExhausted && !$isExpired);
$displayTime = '';
if (!empty($lastCodeTime)) {
    $displayTime = date('Y-m-d H:i:s', strtotime($lastCodeTime));
}

// 剩余次数显示值
$remainingDisplay = $isUnlimited ? '∞' : $remainingAttempts;
$maxDisplay = $isUnlimited ? '∞' : $maxAttempts;

// 格式化教程文字（将换行转换为HTML）
$tutorialTextFormatted = nl2br(htmlspecialchars($tutorialText));

// ========== 提取纯数字用于复制（+852专用） ==========
$codeForCopy = '';
if (!empty($lastCode) && $phoneInfo['type'] == 'hk') {
    $codeForCopy = extractNumbers($lastCode);
    // 如果提取到的数字为空或太短，使用原内容
    if (empty($codeForCopy) || strlen($codeForCopy) < 3) {
        $codeForCopy = $lastCode;
    }
} elseif (!empty($lastCode)) {
    $codeForCopy = $lastCode;
}
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=yes">
    <title><?php echo htmlspecialchars($pageTitle); ?> · 实时验证码</title>
    <style>
        :root {
            --bg: #f0f4f8;
            --card: #ffffff;
            --text: #1a202c;
            --muted: #718096;
            --primary: #4299e1;
            --primary-dark: #3182ce;
            --success: #48bb78;
            --danger: #fc8181;
            --warning: #ed8936;
            --border: #e2e8f0;
            --radius: 16px;
            --shadow: 0 1px 3px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.04);
        }

        * { margin: 0; padding: 0; box-sizing: border-box; }

        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;
            background: var(--bg);
            min-height: 100vh;
            display: flex;
            justify-content: center;
            align-items: flex-start;
            padding: 16px;
            color: var(--text);
            line-height: 1.6;
            transition: background 0.3s ease, color 0.3s ease;
        }

        .page {
            width: 100%;
            max-width: 420px;
            display: flex;
            flex-direction: column;
            gap: 8px;
            padding-top: 6px;
            padding-bottom: 20px;
        }

        .header {
            display: flex;
            align-items: center;
            gap: 12px;
            padding: 6px 4px;
        }

        .header-logo {
            width: 44px;
            height: 44px;
            border-radius: 12px;
            object-fit: cover;
            box-shadow: 0 2px 8px rgba(0,0,0,0.08);
        }

        .header-info h1 {
            font-size: 18px;
            font-weight: 700;
            color: var(--text);
            letter-spacing: -0.3px;
        }

        .header-info span {
            font-size: 11px;
            color: var(--muted);
            font-weight: 500;
        }

        .live-indicator {
            display: flex;
            align-items: center;
            gap: 8px;
            padding: 8px 14px;
            background: var(--card);
            border-radius: 12px;
            font-size: 12px;
            font-weight: 600;
            color: var(--muted);
            box-shadow: var(--shadow);
            border: 1px solid var(--border);
            transition: background 0.3s ease, border-color 0.3s ease;
        }

        .live-dot {
            width: 8px;
            height: 8px;
            border-radius: 50%;
            background: #a0aec0;
            flex-shrink: 0;
        }

        .live-dot.active {
            background: var(--success);
            animation: pulse 1.5s infinite;
        }

        .live-dot.fetching {
            background: var(--warning);
            animation: pulse 0.8s infinite;
        }

        .live-dot.error {
            background: var(--danger);
        }

        @keyframes pulse {
            0%, 100% { opacity: 1; transform: scale(1); }
            50% { opacity: 0.5; transform: scale(1.5); }
        }

        .card {
            background: var(--card);
            border-radius: var(--radius);
            padding: 12px 14px;
            box-shadow: var(--shadow);
            border: 1px solid var(--border);
            transition: background 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease;
        }

        .card-header {
            display: flex;
            align-items: center;
            justify-content: space-between;
            margin-bottom: 6px;
            flex-wrap: wrap;
            gap: 4px;
            min-height: 18px;
        }

        .card-title {
            font-size: 12px;
            font-weight: 600;
            text-transform: uppercase;
            letter-spacing: 0.8px;
            color: var(--muted);
        }

        .card-tag {
            font-size: 10px;
            font-weight: 600;
            padding: 3px 8px;
            border-radius: 10px;
            letter-spacing: 0.3px;
            background: #f7fafc;
            color: var(--muted);
            border: 1px solid var(--border);
        }

        .tag-blue { background: #ebf8ff; color: #2b6cb0; border-color: #bee3f8; }
        .tag-green { background: #f0fff4; color: #276749; border-color: #c6f6d5; }
        .tag-orange { background: #fffaf0; color: #c05621; border-color: #fbd38d; }
        .tag-red { background: #fff5f5; color: #c53030; border-color: #feb2b2; }
        .tag-purple { background: #faf5ff; color: #6b46c1; border-color: #d6bcfa; }
        .tag-unlimited { background: #faf5ff; color: #6b46c1; border: 1px solid #d6bcfa; }

        .value-field {
            background: #f7fafc;
            border: 1px solid var(--border);
            border-radius: 10px;
            padding: 8px 12px;
            font-size: 16px;
            font-weight: 600;
            text-align: center;
            letter-spacing: 0.5px;
            cursor: pointer;
            transition: all 0.2s;
            user-select: all;
            word-break: break-all;
            color: var(--text);
        }

        .value-field:hover {
            border-color: #bee3f8;
            background: #ebf8ff;
        }

        .value-field.code-box {
            font-family: 'SF Mono', 'Fira Code', 'Cascadia Code', monospace;
            font-size: 32px;
            font-weight: 700;
            letter-spacing: 8px;
            color: #2b6cb0;
            padding: 12px 16px;
            background: #ebf8ff;
            border: 2px dashed #bee3f8;
            border-radius: 14px;
        }

        .value-field.code-box.muted {
            color: #a0aec0;
            font-size: 15px;
            letter-spacing: 1px;
            font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', sans-serif;
            font-weight: 400;
            background: #f7fafc;
            border: 2px dashed var(--border);
        }

        .value-field.code-box.danger {
            color: #c53030;
            background: #fff5f5;
            border-color: #feb2b2;
            font-size: 14px;
            letter-spacing: 1px;
            font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', sans-serif;
            font-weight: 500;
        }
        
        .value-field.hk-code {
            font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Microsoft YaHei', sans-serif;
            font-size: 18px;
            letter-spacing: 0.5px;
            font-weight: 600;
            color: #2b6cb0;
            padding: 12px 16px;
            background: #ebf8ff;
            border: 2px dashed #bee3f8;
            border-radius: 14px;
            word-break: break-all;
            white-space: pre-wrap;
            text-align: center;
            line-height: 1.6;
        }

        .value-meta {
            font-size: 11px;
            color: var(--muted);
            text-align: center;
            margin-top: 4px;
        }

        .btn {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            gap: 6px;
            width: 100%;
            padding: 8px 14px;
            border: none;
            border-radius: 10px;
            font-size: 13px;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.2s;
            letter-spacing: 0.3px;
        }

        .btn:active { transform: scale(0.97); }
        .btn:disabled { opacity: 0.4; cursor: not-allowed; transform: none; }

        .btn-primary {
            background: var(--primary);
            color: #fff;
        }
        .btn-primary:hover:not(:disabled) { background: var(--primary-dark); }

        .btn-outline {
            background: transparent;
            border: 1.5px solid var(--border);
            color: var(--text);
        }
        .btn-outline:hover:not(:disabled) { border-color: #cbd5e0; background: #f7fafc; }

        .btn-group {
            display: flex;
            gap: 6px;
            margin-top: 6px;
        }

        .btn-group.single { flex-direction: column; }

        .status-strip {
            margin-top: 6px;
            padding: 6px 10px;
            border-radius: 8px;
            font-size: 12px;
            font-weight: 500;
            text-align: center;
        }

        .strip-info { background: #ebf8ff; color: #2b6cb0; }
        .strip-ok { background: #f0fff4; color: #276749; }
        .strip-warn { background: #fffaf0; color: #c05621; }
        .strip-err { background: #fff5f5; color: #c53030; }

        .tutorial-card {
            background: var(--card);
            border-radius: var(--radius);
            padding: 12px 14px;
            border: 1px solid var(--border);
            box-shadow: var(--shadow);
            font-size: 12px;
            color: var(--text);
            line-height: 1.8;
        }
        .tutorial-card .tutorial-title {
            font-size: 13px;
            font-weight: 600;
            color: var(--muted);
            margin-bottom: 4px;
            display: flex;
            align-items: center;
            gap: 6px;
        }
        .tutorial-card .tutorial-content {
            white-space: pre-wrap;
            word-break: break-word;
        }

        .footer-row {
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 10px;
            font-size: 11px;
            color: var(--muted);
            padding: 2px 0;
        }

        .footer-row .sep {
            width: 3px;
            height: 3px;
            border-radius: 50%;
            background: #cbd5e0;
        }

        .tutorial-entry {
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 6px;
            padding: 10px;
            border-radius: 10px;
            background: var(--card);
            font-size: 13px;
            font-weight: 500;
            color: var(--primary);
            cursor: pointer;
            border: 1px solid var(--border);
            box-shadow: var(--shadow);
            transition: all 0.2s;
        }

        .tutorial-entry:hover { border-color: #bee3f8; background: #ebf8ff; }
        .tutorial-entry:active { transform: scale(0.98); }

        .alert-bar {
            padding: 8px 12px;
            border-radius: 10px;
            font-size: 12px;
            font-weight: 600;
            text-align: center;
        }

        .alert-red { background: #fff5f5; color: #c53030; border: 1px solid #feb2b2; }
        .alert-amber { background: #fffaf0; color: #c05621; border: 1px solid #fbd38d; }

        #toastMsg {
            position: fixed;
            top: 20px;
            left: 50%;
            transform: translateX(-50%);
            z-index: 9999;
            padding: 10px 20px;
            border-radius: 20px;
            font-size: 12px;
            font-weight: 600;
            box-shadow: 0 8px 24px rgba(0,0,0,0.15);
            opacity: 0;
            pointer-events: none;
            transition: opacity 0.3s, transform 0.3s;
            white-space: nowrap;
            letter-spacing: 0.3px;
        }

        #toastMsg.show { opacity: 1; transform: translateX(-50%) translateY(4px); }
        .t-success { background: #276749; color: #fff; }
        .t-error { background: #c53030; color: #fff; }
        .t-warning { background: #c05621; color: #fff; }

        .overlay {
            display: none;
            position: fixed;
            inset: 0;
            background: rgba(0,0,0,0.5);
            z-index: 10000;
            align-items: center;
            justify-content: center;
            backdrop-filter: blur(4px);
            -webkit-backdrop-filter: blur(4px);
            animation: fadeIn 0.3s ease;
        }

        @keyframes fadeIn {
            from { opacity: 0; }
            to { opacity: 1; }
        }

        .overlay.open { display: flex; }

        .dialog {
            background: #fff;
            border-radius: 20px;
            padding: 24px;
            width: 92%;
            max-width: 400px;
            max-height: 90vh;
            overflow-y: auto;
            text-align: center;
            box-shadow: 0 16px 48px rgba(0,0,0,0.2);
            animation: popIn 0.3s ease;
        }

        @keyframes popIn {
            from { opacity: 0; transform: scale(0.9) translateY(10px); }
            to { opacity: 1; transform: scale(1) translateY(0); }
        }

        .dialog::-webkit-scrollbar { width: 4px; }
        .dialog::-webkit-scrollbar-thumb { background: #cbd5e0; border-radius: 4px; }

        .d-close {
            float: right;
            width: 32px;
            height: 32px;
            border-radius: 50%;
            background: #f7fafc;
            border: none;
            cursor: pointer;
            font-size: 16px;
            color: var(--muted);
            transition: background 0.2s;
        }
        .d-close:hover { background: #edf2f7; }

        .d-title {
            font-size: 18px;
            font-weight: 700;
            margin: 6px 0 12px;
            color: #1a202c;
        }

        .d-text {
            font-size: 13px;
            color: #4a5568;
            line-height: 1.8;
            margin-bottom: 10px;
            text-align: left;
        }

        .d-text em {
            font-style: normal;
            font-weight: 600;
            color: #2b6cb0;
            background: #ebf8ff;
            padding: 2px 8px;
            border-radius: 4px;
        }

        .d-divider {
            height: 1px;
            background: #e2e8f0;
            margin: 12px 0;
        }

        .d-note {
            font-size: 11px;
            color: var(--muted);
            margin-bottom: 12px;
        }

        .d-btn {
            width: 100%;
            padding: 12px;
            border: none;
            border-radius: 10px;
            font-size: 14px;
            font-weight: 600;
            cursor: pointer;
            background: var(--primary);
            color: #fff;
            transition: background 0.2s;
        }

        .d-btn:hover { background: var(--primary-dark); }
        .d-btn:active { transform: scale(0.97); }

        .d-images {
            display: flex;
            flex-direction: column;
            gap: 10px;
            margin: 12px 0 16px;
            max-height: 400px;
            overflow-y: auto;
        }

        .d-images::-webkit-scrollbar { width: 3px; }
        .d-images::-webkit-scrollbar-thumb { background: #cbd5e0; border-radius: 4px; }

        .d-images img {
            width: 100%;
            border-radius: 10px;
            border: 1px solid #e2e8f0;
            background: #f7fafc;
        }

        .d-images .img-placeholder {
            padding: 30px;
            background: #f7fafc;
            border-radius: 10px;
            border: 1px dashed #e2e8f0;
            color: #a0aec0;
            font-size: 13px;
            text-align: center;
        }

        a {
            text-decoration: none;
            color: var(--primary);
        }
        
        .activate-success {
            background: #f0fff4;
            border: 1px solid #48bb78;
            border-radius: 8px;
            padding: 8px 12px;
            font-size: 12px;
            color: #276749;
            text-align: center;
        }

        /* 响应式 */
        @media (max-width: 480px) {
            body { padding: 10px; }
            .page { gap: 8px; padding-top: 6px; }
            .card { padding: 10px 12px; }
            .value-field.code-box { font-size: 28px; letter-spacing: 6px; padding: 12px 14px; }
            .value-field.hk-code { font-size: 16px; padding: 12px 14px; }
            .header-logo { width: 38px; height: 38px; }
            .header-info h1 { font-size: 16px; }
            .dialog { padding: 18px; width: 95%; }
            .d-title { font-size: 16px; }
            .tutorial-card { padding: 10px 12px; font-size: 12px; }
        }
    </style>
    
    <!-- 根据系统设置加载对应样式 -->
    <?php if ($styleTemplate !== 'default'): ?>
    <link rel="stylesheet" href="/css/<?php echo $styleTemplate; ?>.css">
    <?php endif; ?>
</head>
<body>
    <div class="page">
        <div id="toastMsg"></div>

        <?php if ($isExpired): ?>
        <div class="alert-bar alert-red">此服务已过期</div>
        <?php elseif ($isAttemptsExhausted && !$hasValidCode): ?>
        <div class="alert-bar alert-amber">验证码次数已用完</div>
        <?php endif; ?>

        <div class="header">
            <img class="header-logo" src="<?php echo htmlspecialchars($pageIcon); ?>" alt="<?php echo htmlspecialchars($pageTitle); ?>" loading="lazy" onerror="this.src='https://tse1-mm.cn.bing.net/th/id/OIP-C.XYR-ifbzUewZ--WCOwvNSQAAAA?w=167&h=180&c=7&r=0&o=7&dpr=1.1&pid=1.7&rm=3'">
            <div class="header-info">
                <h1><?php echo htmlspecialchars($pageTitle); ?></h1>
                <span><?php echo $phoneInfo['type'] == 'hk' ? '+852' : '+1'; ?></span>
            </div>
        </div>

        <div class="live-indicator" id="liveIndicator">
            <span class="live-dot <?php echo $showFetching ? 'fetching' : ($showCode ? 'active' : ''); ?>" id="liveDot"></span>
            <span id="liveText">
                <?php 
                if ($showFetching) echo '正在实时获取验证码...';
                elseif ($showCode) echo '验证码已就绪';
                elseif ($isAttemptsExhausted) echo '次数已用尽';
                else echo '等待中';
                ?>
            </span>
        </div>

     <div class="card">
    <div class="card-header">
        <span class="card-title">📱 手机号</span>
    </div>
    <div class="value-field" id="phone" style="display: flex; align-items: center; justify-content: center; gap: 10px; font-size: 18px;">
        <?php if (!empty($page['phone'])): ?>
        <span style="font-size: 11px; color: var(--muted); background: var(--bg); padding: 2px 10px; border-radius: 12px; border: 1px solid var(--border);">
            <?php echo $phoneInfo['type'] == 'hk' ? '+852' : '+1'; ?>
        </span>
        <span><?php echo htmlspecialchars($phoneNumberOnly); ?></span>
        <?php else: ?>
        <span style="color: var(--muted); font-size: 14px;">暂无可分配手机号</span>
        <?php endif; ?>
    </div>
    <div class="btn-group single">
        <button class="btn btn-outline" onclick="doCopy('phone')" <?php echo ($isExpired || empty($page['phone'])) ? 'disabled' : ''; ?>>
            复制手机号
        </button>
    </div>
</div>

        <div class="card">
            <div class="card-header">
                <span class="card-title">✉️ 验证码</span>
                <div style="display:flex;gap:4px;flex-wrap:wrap;align-items:center;">
                    <?php if ($showCode && !$isAttemptsExhausted): ?>
                    <span class="card-tag tag-blue" id="attBadge">
                        📊 剩余 <?php echo $remainingDisplay; ?>/<?php echo $maxDisplay; ?> 次
                    </span>
                    <?php elseif ($isAttemptsExhausted): ?>
                    <span class="card-tag tag-red">已用尽</span>
                    <?php endif; ?>
                    <?php if ($showCode && $hasValidCode): ?>
                    <span class="card-tag tag-green">已获取</span>
                    <?php endif; ?>
                    <span class="card-tag <?php echo $isUnlimited ? 'tag-unlimited' : 'tag-orange'; ?>">
                        <?php echo $isUnlimited ? '♾️ 无限次' : '🔢 ' . $attemptsLabel; ?>
                    </span>
                </div>
            </div>

            <?php if ($showCode && !empty($lastCode)): ?>
                <?php if ($phoneInfo['type'] == 'hk'): ?>
                    <div class="value-field hk-code" id="codeNumber" data-copy="<?php echo htmlspecialchars($codeForCopy); ?>"><?php echo nl2br(htmlspecialchars($lastCode)); ?></div>
                <?php else: ?>
                    <div class="value-field code-box" id="codeNumber" data-copy="<?php echo htmlspecialchars($lastCode); ?>"><?php echo htmlspecialchars($lastCode); ?></div>
                <?php endif; ?>
                <?php if (!empty($displayTime)): ?>
                <div class="value-meta" id="codeTime">获取时间: <?php echo htmlspecialchars($displayTime); ?></div>
                <?php endif; ?>
            
            <?php elseif ($showFetching): ?>
                <div class="value-field code-box muted" id="codeNumber">等待获取...</div>
                <div class="value-meta" id="codeStatus">正在实时请求验证码</div>
            
            <?php elseif ($isAttemptsExhausted && !$isExpired): ?>
                <div class="value-field code-box danger" id="codeNumber">次数已用完</div>
                <div class="value-meta">无法继续获取</div>
            <?php endif; ?>

            <?php if ($canRenew && !$isUnlimited): ?>
            <div class="btn-group single">
                <button class="btn btn-primary" id="getCodeBtn" onclick="renewCode()">
                    再次获取验证码 (剩余 <?php echo $remainingAttempts; ?> 次)
                </button>
            </div>
            <?php elseif ($canRenew && $isUnlimited): ?>
            <div class="btn-group single">
                <button class="btn btn-primary" id="getCodeBtn" onclick="renewCode()">
                    ♾️ 再次获取验证码 (无限次)
                </button>
            </div>
            <?php elseif ($isAttemptsExhausted && !$isUnlimited): ?>
            <div class="btn-group single">
                <button class="btn btn-primary" id="getCodeBtn" disabled style="background:var(--danger);">
                    次数已用完
                </button>
            </div>
            <?php endif; ?>

            <div class="btn-group">
                <button class="btn btn-outline" id="copyCodeBtn" onclick="doCopy('code')" <?php echo (empty($lastCode) || $isExpired) ? 'disabled' : ''; ?>>
                    复制验证码
                </button>
            </div>

            <?php if ($showFetching): ?>
            <?php elseif ($showCode && !$isAttemptsExhausted): ?>
            <div class="status-strip strip-ok">
                验证码已就绪 · 剩余 <?php echo $remainingDisplay; ?>/<?php echo $maxDisplay; ?> 次
                <?php if ($isUnlimited): ?>
                <span style="color:#6b46c1;margin-left:4px;">♾️</span>
                <?php endif; ?>
            </div>
            <?php endif; ?>
        </div>

        <?php if (!empty($tutorialText)): ?>
        <div class="tutorial-card">
            <div class="tutorial-title">📖 使用说明</div>
            <div class="tutorial-content"><?php echo $tutorialTextFormatted; ?></div>
        </div>
        <?php endif; ?>
        
        <div class="tutorial-entry" onclick="openTutorial()">
            📖 查看完整教程（含图片）
        </div>
        
        <div class="footer-row">
            <span>到期 <?php echo htmlspecialchars($expireTimeFormatted); ?></span>
            <span class="sep"></span>
            <span>ID <?php echo htmlspecialchars($pageCode); ?></span>
        </div>
    </div>

    <div class="overlay" id="welcomeOverlay">
        <div class="dialog">
            <button class="d-close" onclick="closeWelcome()">✕</button>
            <div class="d-title">使用须知</div>
            <div class="d-text" id="welcomeText">
                <?php if ($phoneInfo['type'] == 'hk'): ?>
                请将 <?php echo htmlspecialchars($pageTitle); ?> APP 手机号前缀改为对应地区：<br><em>+86</em> → <em>+852</em>（中国香港）<br><br>
                一台设备限一个账号<br>
                建议更新至最新版本
                <?php else: ?>
                请将 <?php echo htmlspecialchars($pageTitle); ?> APP 手机号前缀改为对应地区：<br><em>+86</em> → <em>+1</em>（加拿大/美国）<br><br>
                一台设备限一个账号<br>
                建议更新至最新版本
                <?php endif; ?>
            </div>
            <div class="d-divider"></div>
            <div class="d-note">多设备同时登录可能导致掉线或封号</div>
            <button class="d-btn" onclick="closeWelcome()">知道了</button>
        </div>
    </div>

    <!-- 教程弹窗 -->
    <div class="overlay" id="tutorialOverlay">
        <div class="dialog">
            <button class="d-close" onclick="closeTutorial()">✕</button>
            <div class="d-title">📖 操作教程</div>
            <div class="d-text">按照以下步骤操作，即可完成验证码获取：</div>
            <div class="d-images">
                <img src="<?php echo htmlspecialchars($tutorialImage); ?>" alt="教程图片" loading="lazy" onerror="this.style.display='none'">
                <div class="img-placeholder" id="imgFallback" style="display:none;">
                    📷 教程图片加载中...<br>
                    <span style="font-size:12px;color:#a0aec0;">请确保图片路径正确</span>
                </div>
            </div>
            <div class="d-divider"></div>
            <button class="d-btn" onclick="closeTutorial()">知道了</button>
        </div>
    </div>

<script>
    document.addEventListener('DOMContentLoaded', function() {
        var img = document.querySelector('.d-images img');
        if (img) {
            img.onerror = function() {
                this.style.display = 'none';
                var fallback = document.getElementById('imgFallback');
                if (fallback) {
                    fallback.style.display = 'block';
                }
            };
        }
    });

    const pageCode = '<?php echo $pageCode; ?>';
    const maxAttempts = <?php echo $maxAttempts; ?>;
    const isUnlimited = <?php echo $isUnlimited ? 'true' : 'false'; ?>;
    let usedCount = <?php echo $usedCount; ?>;
    let remainingAttempts = <?php echo $isUnlimited ? 9999 : $remainingAttempts; ?>;
    let currentCode = '<?php echo addslashes($lastCode); ?>';
    let hasCode = <?php echo $showCode ? 'true' : 'false'; ?>;
    let isFetching = <?php echo $showFetching ? 'true' : 'false'; ?>;
    let currentInterval = null;
    let isRenewing = false;
    let toastTimer = null;

    function toast(msg, type) {
        const el = document.getElementById('toastMsg');
        const cls = { success: 't-success', error: 't-error', warning: 't-warning' };
        el.className = cls[type] || 't-success';
        el.textContent = msg;
        el.classList.add('show');
        clearTimeout(toastTimer);
        toastTimer = setTimeout(() => el.classList.remove('show'), 2400);
    }

    function updateLiveDot(state) {
        const dot = document.getElementById('liveDot');
        const text = document.getElementById('liveText');
        if (!dot || !text) return;
        dot.className = 'live-dot';
        if (state === 'fetching') { dot.classList.add('fetching'); text.textContent = '正在实时获取验证码...'; }
        else if (state === 'active') { dot.classList.add('active'); text.textContent = '验证码已就绪'; }
        else if (state === 'error') { dot.classList.add('error'); text.textContent = '次数已用完'; }
        else { text.textContent = '等待中'; }
    }

    if (isFetching && !hasCode) {
        updateLiveDot('fetching');
        startFirstFetch();
    }

    function startFirstFetch() {
        if (currentInterval) clearInterval(currentInterval);
        let fetchCount = 0;

        function doFetch() {
            fetchCount++;
            const statusDiv = document.getElementById('codeStatus');
            if (statusDiv) { statusDiv.textContent = '正在实时请求... (第' + fetchCount + '次)'; }

            fetch('', {
                method: 'POST',
                headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
                body: 'action=fetch_api'
            })
            .then(r => r.json())
            .then(data => {
                if (data.success && data.code) {
                    clearInterval(currentInterval);
                    updateLiveDot('active');
                    toast('验证码获取成功', 'success');
                    setTimeout(() => location.reload(), 500);
                } else if (data.noAttempts) {
                    clearInterval(currentInterval);
                    updateLiveDot('error');
                    toast('次数已用完', 'error');
                    setTimeout(() => location.reload(), 3000);
                } else if (data.noCode || data.duplicate || data.sameAsCurrent) {
                    if (statusDiv) { 
                        statusDiv.textContent = (data.message || '继续等待...') + ' (第' + fetchCount + '次)'; 
                    }
                } else if (data.forbidden) {
                    if (statusDiv) { 
                        statusDiv.textContent = '🚫 验证码包含违禁词，已过滤 (第' + fetchCount + '次)'; 
                    }
                }
            })
            .catch(err => {
                console.error('fetch error:', err);
            });
        }

        doFetch();
        currentInterval = setInterval(doFetch, 3000);
    }

    function renewCode() {
        if (!isUnlimited && remainingAttempts <= 0) { 
            toast('次数已用完', 'error'); 
            return; 
        }
        if (isRenewing) { toast('正在获取中...', 'warning'); return; }

        isRenewing = true;
        updateLiveDot('fetching');

        const btn = document.getElementById('getCodeBtn');
        if (btn) { btn.disabled = true; btn.textContent = '正在实时获取...'; }

        const statusDiv = document.getElementById('codeStatus');
        if (statusDiv) { statusDiv.textContent = '正在实时请求新验证码...'; }

        let fetchCount = 0;

        function doRenewFetch() {
            fetchCount++;
            if (statusDiv) { statusDiv.textContent = '正在实时请求... (第' + fetchCount + '次)'; }

            fetch('', {
                method: 'POST',
                headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
                body: 'action=renew_code'
            })
            .then(r => r.json())
            .then(data => {
                if (data.success && data.code) {
                    clearInterval(currentInterval);
                    isRenewing = false;
                    updateLiveDot('active');
                    toast('新验证码获取成功', 'success');
                    setTimeout(() => location.reload(), 800);
                } else if (data.noAttempts) {
                    clearInterval(currentInterval);
                    isRenewing = false;
                    updateLiveDot('error');
                    toast('次数已用完', 'error');
                    setTimeout(() => location.reload(), 3000);
                } else if (data.noCode || data.duplicate || data.sameAsCurrent) {
                    if (statusDiv) { 
                        statusDiv.textContent = (data.message || '继续等待...') + ' (第' + fetchCount + '次)'; 
                    }
                } else if (data.forbidden) {
                    if (statusDiv) { 
                        statusDiv.textContent = '🚫 验证码包含违禁词，已过滤 (第' + fetchCount + '次)'; 
                    }
                }
            })
            .catch(err => {
                console.error('renew error:', err);
            });
        }

        if (currentInterval) clearInterval(currentInterval);
        doRenewFetch();
        currentInterval = setInterval(doRenewFetch, 3000);
    }

    window.addEventListener('load', () => {
        if (!sessionStorage.getItem('welcomeTxsp')) {
            setTimeout(() => document.getElementById('welcomeOverlay').classList.add('open'), 400);
            sessionStorage.setItem('welcomeTxsp', 'true');
        }
    });

    function closeWelcome() { document.getElementById('welcomeOverlay').classList.remove('open'); }
    function openTutorial() { document.getElementById('tutorialOverlay').classList.add('open'); }
    function closeTutorial() { document.getElementById('tutorialOverlay').classList.remove('open'); }

    document.addEventListener('click', e => {
        if (e.target.classList.contains('overlay')) e.target.classList.remove('open');
    });
function doCopy(id) {
    let text = '';
    let type = '';
    
    if (id === 'code') {
        const codeDiv = document.getElementById('codeNumber');
        if (!codeDiv) { toast('验证码元素不存在', 'error'); return; }
        
        // 优先使用 data-copy 属性（纯数字版本）
        const copyData = codeDiv.getAttribute('data-copy');
        if (copyData) {
            text = copyData.trim();
        } else {
            text = codeDiv.textContent.trim();
        }
        
        type = 'code';
        const blocked = ['等待获取', '次数已用完', '获取中', '暂无验证码'];
        for (let i = 0; i < blocked.length; i++) {
            if (text.indexOf(blocked[i]) !== -1) {
                toast('请先获取验证码', 'warning');
                return;
            }
        }
        if (text.length < 3) {
            toast('验证码无效，请重新获取', 'warning');
            return;
        }
    } else {
        const el = document.getElementById('phone');
        if (!el) { toast('手机号元素不存在', 'error'); return; }
        const phoneText = el.textContent.trim();
        // 提取所有数字
        const numMatch = phoneText.match(/(\d+)/g);
        if (numMatch) {
            // 取最后一段数字（手机号），如果只有一段则取全部
            text = numMatch[numMatch.length - 1];
        } else {
            text = phoneText.replace(/[^0-9]/g, '');
        }
        type = 'phone';
    }

    if (!text || text.length === 0) {
        toast('没有可复制的内容', 'warning');
        return;
    }

    if (navigator.clipboard && navigator.clipboard.writeText) {
        navigator.clipboard.writeText(text)
            .then(() => {
                toast('✅ 已复制: ' + text, 'success');
                recordCopy(type);
            })
            .catch(() => fallbackCopy(text, type));
    } else {
        fallbackCopy(text, type);
    }
}

    function fallbackCopy(text, type) {
        const ta = document.createElement('textarea');
        ta.value = text;
        ta.style.cssText = 'position:fixed;left:-9999px;top:-9999px;width:1px;height:1px;opacity:0;';
        document.body.appendChild(ta);
        ta.focus();
        ta.select();
        ta.setSelectionRange(0, text.length);
        
        try {
            const success = document.execCommand('copy');
            if (success) {
                toast('✅ 已复制: ' + text, 'success');
                recordCopy(type);
            } else {
                toast('❌ 复制失败，请手动复制', 'error');
            }
        } catch (e) {
            toast('❌ 复制失败，请手动复制', 'error');
        }
        document.body.removeChild(ta);
    }

    function recordCopy(type) {
        fetch('', { 
            method: 'POST', 
            headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, 
            body: 'action=record_copy&type=' + encodeURIComponent(type) 
        }).catch(err => console.error('record copy error:', err));
    }

    window.doCopy = doCopy;
    window.renewCode = renewCode;
    window.openTutorial = openTutorial;
    window.closeTutorial = closeTutorial;
    window.closeWelcome = closeWelcome;
</script>
</body>
</html>