<?php

/**
 * @id 31
 * @name 文件/目录效验修复
 * @version 1.0.0
 * @description 效验网站文件和目录是否完整，确保网站结构的完整性，及时发现并下载云端标准文件进行修复缺失文件
 * @price 0
 * @type 工具
 * @website 
 * @width 600
 * @height 600
 * @thumbnail /img/id31.png
 */

if (!function_exists('get_file_structure_cn_map')) {
    require_once dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR . 'common.php';
}

if (!function_exists('qk_license_verify') && is_file(dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR . 'license.php')) {
    require_once dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR . 'license.php';
}

function qk_filecheck_auth_ticket()
{
    if (isset($_SESSION['qkcms_license_cache']['data']['auth_ticket']) && $_SESSION['qkcms_license_cache']['data']['auth_ticket'] !== '') {
        return (string)$_SESSION['qkcms_license_cache']['data']['auth_ticket'];
    }
    if (function_exists('qk_license_verify')) {
        $data = qk_license_verify();
        if (is_array($data) && !empty($data['auth_ticket'])) {
            return (string)$data['auth_ticket'];
        }
    }
    return '';
}

// 大小写不敏感的文件存在检查
function file_exists_case_insensitive($root, $path)
{
    try {
        // 统一处理路径分隔符
        $path = str_replace('/', DIRECTORY_SEPARATOR, $path);
        $full_path = $root . DIRECTORY_SEPARATOR . $path;

        // 直接检查文件是否存在
        if (file_exists($full_path)) {
            return true;
        }

        // 尝试使用真实路径检查
        $real_path = realpath($full_path);
        if ($real_path !== false) {
            return true;
        }

        // 尝试检查目录中的文件（处理中文文件名问题）
        $parts = explode(DIRECTORY_SEPARATOR, $path);
        $file_name = array_pop($parts);
        $dir_path = $root . DIRECTORY_SEPARATOR . implode(DIRECTORY_SEPARATOR, $parts);

        if (is_dir($dir_path)) {
            // 尝试使用不同的编码处理方式
            $file_name_utf8 = $file_name;
            $file_name_gbk = mb_convert_encoding($file_name, 'GBK', 'UTF-8');

            // 使用glob函数尝试匹配文件名（支持中文）
            $glob_pattern = $dir_path . DIRECTORY_SEPARATOR . '*';
            $files = glob($glob_pattern);
            if ($files !== false) {
                foreach ($files as $file) {
                    $basename = basename($file);
                    // 不区分大小写比较文件名
                    if (strtolower($basename) === strtolower($file_name_utf8) || strtolower($basename) === strtolower($file_name_gbk)) {
                        return true;
                    }
                }
            }

            // 如果glob失败，尝试使用scandir
            $files = scandir($dir_path);
            if ($files !== false) {
                foreach ($files as $file) {
                    if ($file === '.' || $file === '..') continue;
                    // 不区分大小写比较文件名
                    if (strtolower($file) === strtolower($file_name_utf8) || strtolower($file) === strtolower($file_name_gbk)) {
                        return true;
                    }
                }
            }
        }
    } catch (Exception $e) {
        // 发生错误时返回false
    }

    return false;
}

// 获取需要检查的文件和目录
function getFilesToCheck()
{
    $grouped_files = array(
        '根目录文件' => array(),
        'admin目录' => array(),
        'templates目录' => array(),
        'assets目录' => array(),
        'uploads子目录' => array(),
        'toolsrc目录' => array()
    );

    foreach (get_file_structure_cn_map() as $path => $description) {
        $path = str_replace('\\', '/', (string)$path);
        if (strpos($path, 'admin/') === 0) {
            $grouped_files['admin目录'][] = $path;
        } elseif (strpos($path, 'templates/') === 0) {
            $grouped_files['templates目录'][] = $path;
        } elseif (strpos($path, 'assets/') === 0) {
            $grouped_files['assets目录'][] = $path;
        } elseif (strpos($path, 'uploads/') === 0) {
            $grouped_files['uploads子目录'][] = $path;
        } elseif (strpos($path, 'toolsrc/') === 0) {
            $grouped_files['toolsrc目录'][] = $path;
        } else {
            $grouped_files['根目录文件'][] = $path;
        }
    }

    return $grouped_files;
}

if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['plugin_action']) && $_POST['plugin_action'] == 'repair_item') {
    header('Content-Type: application/json; charset=utf-8');
    try {
        $root_path = realpath(dirname(__DIR__, 2));
        if ($root_path === false) {
            echo json_encode(['success' => false, 'message' => '站点根目录获取失败'], JSON_UNESCAPED_UNICODE);
            exit;
        }

        $path = isset($_POST['path']) ? (string)$_POST['path'] : '';
        $path = str_replace('\\', '/', $path);
        $path = ltrim($path, '/');
        $path = preg_replace('/[[:cntrl:]]/', '', $path);
        if ($path === '' || strpos($path, '..') !== false) {
            echo json_encode(['success' => false, 'message' => '路径参数错误'], JSON_UNESCAPED_UNICODE);
            exit;
        }

        $is_directory = isset($_POST['is_directory']) ? (int)$_POST['is_directory'] : 0;
        $is_directory = $is_directory ? 1 : 0;

        $full_path = $root_path . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $path);
        $parent_dir = dirname($full_path);

        if ($is_directory) {
            if (is_dir($full_path)) {
                echo json_encode(['success' => true, 'message' => '目录已存在', 'path' => $path], JSON_UNESCAPED_UNICODE);
                exit;
            }
            if (!@mkdir($full_path, 0755, true) && !is_dir($full_path)) {
                echo json_encode(['success' => false, 'message' => '目录创建失败', 'path' => $path], JSON_UNESCAPED_UNICODE);
                exit;
            }
            echo json_encode(['success' => true, 'message' => '目录修复成功', 'path' => $path], JSON_UNESCAPED_UNICODE);
            exit;
        }

        if (!is_dir($parent_dir)) {
            if (!@mkdir($parent_dir, 0755, true) && !is_dir($parent_dir)) {
                echo json_encode(['success' => false, 'message' => '上级目录不存在且创建失败', 'path' => $path], JSON_UNESCAPED_UNICODE);
                exit;
            }
        }

        $real_root = realpath($root_path);
        $real_parent = realpath($parent_dir);
        $root_prefix = $real_root !== false ? strtolower($real_root) : '';
        $parent_norm = $real_parent !== false ? strtolower($real_parent) : '';
        if ($real_root === false || $real_parent === false || !($parent_norm === $root_prefix || strpos($parent_norm, $root_prefix . strtolower(DIRECTORY_SEPARATOR)) === 0)) {
            echo json_encode(['success' => false, 'message' => '路径越界', 'path' => $path], JSON_UNESCAPED_UNICODE);
            exit;
        }

        $host = isset($_SERVER['HTTP_HOST']) ? trim((string)$_SERVER['HTTP_HOST']) : '';
        $host = preg_replace('#^https?://#i', '', $host);
        $host = preg_replace('#/.*$#', '', $host);
        $host = strtolower($host);
        $host = preg_replace('/:\d+$/', '', $host);
        if ($host === '') {
            echo json_encode(['success' => false, 'message' => '站点域名获取失败', 'path' => $path], JSON_UNESCAPED_UNICODE);
            exit;
        }

        $cloud_base = defined('QKCMS_CLOUD_BASE_URL') ? (string)QKCMS_CLOUD_BASE_URL : '';
        if ($cloud_base === '') {
            echo json_encode(['success' => false, 'message' => '云端接口未配置', 'path' => $path], JSON_UNESCAPED_UNICODE);
            exit;
        }

        $ticket = qk_filecheck_auth_ticket();
        if ($ticket === '') {
            echo json_encode(['success' => false, 'message' => '授权票据获取失败', 'path' => $path], JSON_UNESCAPED_UNICODE);
            exit;
        }
        
        $action = 'system_file';

        $url = rtrim($cloud_base, '/') . '/license_api.php?action=' . urlencode($action) .
            '&site=' . urlencode($host) .
            '&path=' . urlencode($path) .
            '&ticket=' . urlencode($ticket);

        $http_code = 0;
        $body = '';
        if (function_exists('curl_init')) {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 8);
            curl_setopt($ch, CURLOPT_TIMEOUT, 25);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
            $body = curl_exec($ch);
            $http_code = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
            curl_close($ch);
        } else {
            $ctx = stream_context_create([
                'http' => [
                    'method' => 'GET',
                    'timeout' => 25,
                    'header' => "User-Agent: QKCMS\r\n"
                ]
            ]);
            $body = @file_get_contents($url, false, $ctx);
            $http_code = 200;
            if (isset($http_response_header) && is_array($http_response_header)) {
                foreach ($http_response_header as $h) {
                    if (preg_match('#^HTTP/\\S+\\s+(\\d+)#i', $h, $m)) {
                        $http_code = (int)$m[1];
                        break;
                    }
                }
            }
        }

        if ($http_code !== 200 || !is_string($body) || $body === '') {
            $msg = '云端获取失败';
            if ($http_code === 404) $msg = '云端文件不存在';
            elseif ($http_code === 403) $msg = '云端接口校验失败';
            elseif ($http_code === 429) $msg = '云端请求过于频繁';
            
            // 调试信息：记录URL和响应
            error_log("修复请求失败 - URL: " . $url . ", HTTP代码: " . $http_code . ", 响应长度: " . strlen($body));
            
            echo json_encode(['success' => false, 'message' => $msg, 'path' => $path, 'http_code' => $http_code, 'debug_url' => $url], JSON_UNESCAPED_UNICODE);
            exit;
        }

        $written = @file_put_contents($full_path, $body, LOCK_EX);
        if ($written === false || $written <= 0) {
            echo json_encode(['success' => false, 'message' => '写入文件失败', 'path' => $path], JSON_UNESCAPED_UNICODE);
            exit;
        }

        echo json_encode(['success' => true, 'message' => '文件修复成功', 'path' => $path, 'bytes' => (int)$written], JSON_UNESCAPED_UNICODE);
        exit;
    } catch (Exception $e) {
        echo json_encode(['success' => false, 'message' => '修复异常: ' . $e->getMessage()], JSON_UNESCAPED_UNICODE);
        exit;
    }
}

// 处理文件检查请求
if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['plugin_action']) && $_POST['plugin_action'] == 'check_files') {
    try {
        $root_path = realpath(dirname(__DIR__, 2));
        $files_to_check = getFilesToCheck();

        $result = [
            'success' => true,
            'total_files' => 0,
            'existing_files' => 0,
            'missing_files' => [],
            'categories' => [],
            'directories' => [
                'total' => 5,
                'existing' => 0,
                'missing' => []
            ]
        ];

        // 检查主要目录
        $main_dirs = [
            'uploads',
            'templates',
            'assets',
            'admin',
            'toolsrc'
        ];

        foreach ($main_dirs as $dir) {
            $dir_path = $root_path . '/' . $dir;
            if (is_dir($dir_path)) {
                $result['directories']['existing']++;
            } else {
                $result['directories']['missing'][] = $dir;
            }
        }

        // 检查文件
        foreach ($files_to_check as $category => $files) {
            $category_result = [
                'name' => $category,
                'total' => count($files),
                'existing' => 0,
                'missing' => []
            ];

            foreach ($files as $file_path) {
                $result['total_files']++;
                $full_path = $root_path . '/' . $file_path;

                // 检查文件是否存在（不区分大小写）
                if (file_exists_case_insensitive($root_path, $file_path)) {
                    $category_result['existing']++;
                    $result['existing_files']++;
                } else {
                    $category_result['missing'][] = $file_path;
                    $result['missing_files'][] = $file_path;
                }
            }

            $result['categories'][] = $category_result;
        }

        // 返回JSON响应
        header('Content-Type: application/json');
        echo json_encode($result, JSON_UNESCAPED_UNICODE);
        exit;
    } catch (Exception $e) {
        // 返回错误响应
        header('Content-Type: application/json');
        echo json_encode(['success' => false, 'error' => $e->getMessage()]);
        exit;
    }
}

$file_descriptions = get_file_structure_cn_map();
$files_to_check = getFilesToCheck();
$checked_items = array();
foreach ($files_to_check as $category_files) {
    foreach ($category_files as $file_path) {
        $checked_items[$file_path] = $file_path;
    }
}
$file_descriptions_json = json_encode($file_descriptions, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
$checked_items_json = json_encode(array_values($checked_items), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
?>
<div class="file-check-tool">
    <div class="header">
        <div class="header-content">
            <p class="description">本效验工具用于检查网站文件和目录是否完整，确保网站结构的完整性</p>
            <div id="result-summary" class="result-summary" style="display: none;">
                <div class="summary-card">
                    <span class="summary-item file-stats">
                        <span id="file-stats" class="value">原文件0/现文件0</span>
                    </span>
                    <span class="separator">|</span>
                    <span class="summary-item dir-stats">
                        <span id="dir-stats" class="value">原目录0/现目录0</span>
                    </span>
                </div>
            </div>
        </div>
    </div>

    <div class="action-buttons">
        <button id="check-btn" class="btn primary-btn">开始效验</button>
        <button id="missing-btn" class="btn warning-btn" style="display: none;">查看缺失列表</button>
        <button id="repair-all-btn" class="btn repairall-btn" style="display:none;">一键修复全部</button>
        <button id="clear-btn" class="btn secondary-btn">清空结果</button>
    </div>

    <div class="result-container">
        <div id="loading" class="loading" style="display: none;">
            <div class="loading-spinner"></div>
            <p>正在效验文件...请稍候</p>
        </div>

        <div id="result-details" class="result-details" style="display: none;">
            <h4>详细结果</h4>
            <div class="table-container">
                <table class="files-table" id="files-table">
                    <thead>
                        <tr>
                            <th>文件/目录</th>
                            <th>用途说明</th>
                            <th>状态</th>
                            <th>操作</th>
                        </tr>
                    </thead>
                    <tbody id="files-table-body">
                    </tbody>
                </table>
            </div>
        </div>

    </div>
</div>

<style>
    .file-check-tool {
        padding: 16px;
        border-radius: 8px;
        border: 1px solid #e0e0e0;
        font-family: 'Microsoft YaHei', '微软雅黑', sans-serif;
        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
        background-color: #ffffff;
        padding-bottom: 0px;
    }

    .header {
        text-align: center;
        margin-bottom: 16px;
        padding-bottom: 12px;
        border-bottom: 1px solid #f0f0f0;
    }

    .header-content {
        display: flex;
        align-items: center;
        justify-content: center;
        flex-wrap: wrap;
        gap: 20px;
    }

    .description {
        margin: 0;
        color: #666666;
        font-size: 13px;
        line-height: 1.4;
    }

    .result-summary {
        margin: 0;
    }

    .summary-card {
        display: flex;
        align-items: center;
        gap: 15px;
    }

    .summary-item {
        display: flex;
        align-items: center;
    }

    .summary-item .value {
        font-size: 13px;
        font-weight: 600;
    }

    .file-stats .value {
        color: #2196F3;
    }

    .dir-stats .value {
        color: #4CAF50;
    }

    .separator {
        color: #cccccc;
        margin: 0 5px;
    }

    /* 美化滚动条 */
    .table-container::-webkit-scrollbar {
        width: 8px;
        height: 8px;
    }

    .table-container::-webkit-scrollbar-track {
        background: #f1f1f1;
        border-radius: 4px;
    }

    .table-container::-webkit-scrollbar-thumb {
        background: #c1c1c1;
        border-radius: 4px;
    }

    .table-container::-webkit-scrollbar-thumb:hover {
        background: #a1a1a1;
    }

    .action-buttons {
        display: flex;
        gap: 10px;
        justify-content: center;
        margin-bottom: 16px;
    }

    .btn {
        padding: 8px 20px;
        border: none;
        border-radius: 6px;
        font-size: 13px;
        font-weight: 500;
        cursor: pointer;
        transition: all 0.3s ease;
        font-family: 'Microsoft YaHei', '微软雅黑', sans-serif;
    }

    .primary-btn {
        background: #2196F3;
        color: white;
    }

    .primary-btn:hover {
        background: #1976D2;
        transform: translateY(-1px);
        box-shadow: 0 2px 4px rgba(33, 150, 243, 0.3);
    }

    .secondary-btn {
        background: #f5f5f5;
        color: #666666;
        border: 1px solid #e0e0e0;
    }

    .secondary-btn:hover {
        background: #e0e0e0;
        transform: translateY(-1px);
        box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
    }

    .warning-btn {
        background: #ff9800;
        color: white;
    }

    .warning-btn:hover {
        background: #f57c00;
        transform: translateY(-1px);
        box-shadow: 0 2px 4px rgba(255, 152, 0, 0.3);
    }

    .repairall-btn {
        background: #ff5722;
        color: white;
    }

    .repairall-btn:hover {
        background: #e64a19;
        transform: translateY(-1px);
        box-shadow: 0 2px 4px rgba(255, 87, 34, 0.3);
    }

    .result-container {
        min-height: 250px;
    }

    .loading {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        padding: 40px 0;
    }

    .loading-spinner {
        width: 32px;
        height: 32px;
        border: 3px solid #f3f3f3;
        border-top: 3px solid #2196F3;
        border-radius: 50%;
        animation: spin 1s linear infinite;
        margin-bottom: 12px;
    }

    @keyframes spin {
        0% {
            transform: rotate(0deg);
        }

        100% {
            transform: rotate(360deg);
        }
    }

    .loading p {
        color: #666666;
        font-size: 13px;
    }

    .result-details {
        border-top: 1px solid #f0f0f0;
        padding-top: 12px;
    }

    .result-details h4 {
        margin: 0 0 12px 0;
        color: #333333;
        font-size: 15px;
        font-weight: 600;
    }

    .categories-list {
        max-height: 280px;
        overflow-y: auto;
    }

    .category-item {
        background: #ffffff;
        border: 1px solid #e0e0e0;
        border-radius: 6px;
        padding: 12px;
        margin-bottom: 8px;
        transition: all 0.3s ease;
    }

    .category-item:hover {
        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
    }

    .category-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 6px;
    }

    .category-name {
        font-size: 14px;
        font-weight: 600;
        color: #333333;
    }

    .category-stats {
        font-size: 12px;
        color: #666666;
    }

    .category-status {
        padding: 3px 10px;
        border-radius: 10px;
        font-size: 11px;
        font-weight: 500;
    }

    .missing-files {
        margin-top: 6px;
        padding: 6px;
        background: #fff3cd;
        border: 1px solid #ffeaa7;
        border-radius: 4px;
        font-size: 11px;
        color: #856404;
    }

    .status-complete {
        color: #2e7d32;
        font-weight: 500;
    }

    .status-incomplete {
        color: #c62828;
        font-weight: 500;
    }

    .missing-file {
        color: #c62828;
        font-weight: 500;
    }



    .table-container {
        height: 290px;
        overflow-y: auto;
        border: 1px solid #e0e0e0;
        border-radius: 6px;
        margin-bottom: 15px
    }

    .files-table {
        width: 100%;
        border-collapse: collapse;
        font-size: 12px;
        table-layout: fixed;
    }

    .files-table th,
    .files-table td {
        padding: 8px 12px;
        text-align: left;
        border-bottom: 1px solid #f0f0f0;
    }

    .files-table th {
        background: #f8f9fa;
        font-weight: 600;
        color: #333333;
        position: sticky;
        top: 0;
        z-index: 1;
    }

    .files-table th:nth-child(1),
    .files-table td:nth-child(1) {
        min-width: 150px;
        max-width: 250px;
    }

    .files-table th:nth-child(2),
    .files-table td:nth-child(2) {
        min-width: 150px;
        max-width: 300px;
    }

    .files-table.mode-all th:nth-child(4),
    .files-table.mode-all td:nth-child(4) {
        display: none;
    }

    .files-table td {
        color: #666666;
    }

    .files-table td.action-cell {
        white-space: nowrap;
    }

    .files-table th:nth-child(3),
    .files-table td:nth-child(3) {
        width: 110px;
        text-align: center;
        white-space: nowrap;
    }

    .files-table th:nth-child(4),
    .files-table td:nth-child(4) {
        text-align: right;
    }

    .repair-action {
        padding: 4px 0;
        border: none;
        border-radius: 4px;
        font-size: 12px;
        cursor: pointer;
        background: #2196F3;
        color: #fff;
        width: 48px;
        text-align: center;
    }

    .repair-action[disabled] {
        opacity: 0.65;
        cursor: not-allowed;
    }

    .files-table tr:hover {
        background: #f8f9fa;
    }

    .files-table td:first-child {
        font-family: 'Courier New', monospace;
        color: #2196F3;
        font-weight: 500;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        max-width: 0;
    }

    .files-table td:nth-child(2) {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        max-width: 0;
    }

    .status-complete {
        color: #2e7d32;
        font-weight: 500;
    }

    .status-incomplete {
        color: #c62828;
        font-weight: 500;
    }

    /* 滚动条样式 */
    .categories-list::-webkit-scrollbar {
        width: 6px;
    }

    .categories-list::-webkit-scrollbar-track {
        background: #f1f1f1;
        border-radius: 3px;
    }

    .categories-list::-webkit-scrollbar-thumb {
        background: #c1c1c1;
        border-radius: 3px;
    }

    .categories-list::-webkit-scrollbar-thumb:hover {
        background: #a1a1a1;
    }
</style>

<script>
    (function() {
        const fileDescriptions = <?php echo $file_descriptions_json; ?>;
        const checkedItems = <?php echo $checked_items_json; ?>;

        function escapeHtml(input) {
            return String(input || '').replace(/[&<>"']/g, function(c) {
                return {
                    '&': '&amp;',
                    '<': '&lt;',
                    '>': '&gt;',
                    '"': '&quot;',
                    "'": '&#39;'
                }[c];
            });
        }

        function cssEscapeCompat(input) {
            return String(input || '')
                .replace(/\\/g, '\\\\')
                .replace(/"/g, '\\"')
                .replace(/\r/g, '')
                .replace(/\n/g, '')
                .replace(/\f/g, '');
        }

        function normalizePath(path) {
            return String(path || '').replace(/\\/g, '/').replace(/\/+$/, '');
        }

        function getDescription(path) {
            const normalizedPath = normalizePath(path);
            return fileDescriptions[path] || fileDescriptions[normalizedPath] || fileDescriptions[normalizedPath + '/'] || '未知用途';
        }

        function isPathMissing(paths, targetPath) {
            const normalizedTargetPath = normalizePath(targetPath);
            return paths.some(path => normalizePath(path) === normalizedTargetPath);
        }

        function isDirectoryPath(path) {
            const normalizedPath = String(path || '').replace(/\\/g, '/');
            return normalizedPath.endsWith('/') || !normalizedPath.split('/').pop().includes('.');
        }

        // 定义callParentToast函数，使用父页面的提示框
        function callParentToast(message, options = {}) {
            if (window.parent && window.parent.postMessage) {
                window.parent.postMessage({
                    type: 'toast',
                    func: 'showToast',
                    message: message,
                    options: options
                }, '*');
            } else {
                // 降级处理：使用alert
                alert(message);
            }
        }

        // 元素获取
        const checkBtn = document.getElementById('check-btn');
        const clearBtn = document.getElementById('clear-btn');
        const missingBtn = document.getElementById('missing-btn');
        const loading = document.getElementById('loading');
        const resultSummary = document.getElementById('result-summary');
        const resultDetails = document.getElementById('result-details');
        const fileStats = document.getElementById('file-stats');
        const dirStats = document.getElementById('dir-stats');
        const filesTable = document.getElementById('files-table');
        const repairAllBtn = document.getElementById('repair-all-btn');

        // 存储效验结果
        let currentResult = null;

        function setTableMode(mode) {
            if (!filesTable) return;
            filesTable.classList.remove('mode-all', 'mode-missing');
            if (mode === 'missing') filesTable.classList.add('mode-missing');
            else filesTable.classList.add('mode-all');
            // 注意：一键修复按钮的显示逻辑现在由displayResult函数控制
            // 不再根据表格模式来控制显示
        }

        function refreshSummaryFromCurrentResult() {
            if (!currentResult) return;
            fileStats.textContent = `原文件${currentResult.total_files}/现文件${currentResult.existing_files}`;
            dirStats.textContent = `原目录${currentResult.directories.total}/现目录${currentResult.directories.existing}`;
        }

        // 开始效验按钮点击事件
        checkBtn.addEventListener('click', function() {
            // 执行文件检查
            const xhr = new XMLHttpRequest();
            xhr.open('POST', '/admin/Plugin.php', true);
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
            xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
            xhr.onreadystatechange = function() {
                if (xhr.readyState === 4) {

                    if (xhr.status === 200) {
                        try {
                            const response = JSON.parse(xhr.responseText);
                            if (response.success) {
                                // 显示结果
                                displayResult(response);
                            } else {
                                // 显示错误
                                callParentToast('效验失败: ' + (response.error || response.message), {
                                    type: 'error'
                                });
                            }
                        } catch (e) {
                            callParentToast('效验失败: 响应格式错误', {
                                type: 'error'
                            });
                        }
                    } else {
                        callParentToast('效验失败: 网络错误', {
                            type: 'error'
                        });
                    }
                }
            };
            xhr.send('plugin=31_filecheck&plugin_action=check_files');
        });

        // 清空结果按钮点击事件
        clearBtn.addEventListener('click', function() {
            resultSummary.style.display = 'none';
            resultDetails.style.display = 'none';
            missingBtn.style.display = 'none';
            const filesTableBody = document.getElementById('files-table-body');
            if (filesTableBody) {
                filesTableBody.innerHTML = '';
            }
            setTableMode('all');
        });

        // 显示缺少文件按钮点击事件
        missingBtn.addEventListener('click', function() {
            if (currentResult) {
                setTableMode('missing');
                // 获取表格主体
                const filesTableBody = document.getElementById('files-table-body');
                if (filesTableBody) {
                    // 清空表格
                    filesTableBody.innerHTML = '';

                    // 收集所有缺少的文件
                    const missingItems = [];
                    const missingSet = new Set();

                    // 添加缺失的目录
                    currentResult.directories.missing.forEach(dir => {
                        const normalizedDir = normalizePath(dir);
                        if (!missingSet.has(normalizedDir)) {
                            missingSet.add(normalizedDir);
                            missingItems.push({
                                path: dir,
                                exists: false,
                                isDirectory: true
                            });
                        }
                    });

                    // 添加缺失的文件
                    currentResult.missing_files.forEach(file => {
                        const normalizedFile = normalizePath(file);
                        if (!missingSet.has(normalizedFile)) {
                            missingSet.add(normalizedFile);
                            missingItems.push({
                                path: file,
                                exists: false,
                                isDirectory: isDirectoryPath(file)
                            });
                        }
                    });

                    // 按路径排序
                    missingItems.sort((a, b) => a.path.localeCompare(b.path));

                    // 生成表格行
                    missingItems.forEach(item => {
                        const row = document.createElement('tr');
                        const status = '❌ 缺失';
                        const statusClass = 'status-incomplete';
                        const pathClass = 'missing-file';
                        const description = getDescription(item.path);
                        const actionHtml = `<button type="button" class="repair-action" data-path="${escapeHtml(item.path)}" data-is-dir="${item.isDirectory ? 1 : 0}">修复</button>`;

                        row.innerHTML = `
                            <td class="${pathClass}">${escapeHtml(item.path)}</td>
                            <td>${escapeHtml(description)}</td>
                            <td class="${statusClass}">${status}</td>
                            <td class="action-cell">${actionHtml}</td>
                        `;
                        filesTableBody.appendChild(row);
                    });

                    // 确保结果区域显示
                    resultDetails.style.display = 'block';
                }
            }
        });

        // 显示效验结果
        function displayResult(data) {
            console.log('收到效验结果:', data); // 调试信息
            setTableMode('all');

            // 计算文件统计
            const totalFiles = data.total_files;
            const existingFiles = data.existing_files;
            const missingFiles = data.total_files - data.existing_files;

            // 使用后端提供的目录统计数据
            const totalDirs = data.directories.total;
            const existingDirs = data.directories.existing;
            const missingDirs = totalDirs - existingDirs;

            // 显示统计信息
            fileStats.textContent = `原文件${totalFiles}/现文件${existingFiles}`;
            dirStats.textContent = `原目录${totalDirs}/现目录${existingDirs}`;
            resultSummary.style.display = 'block';

            // 生成详细结果表格
            const filesTableBody = document.getElementById('files-table-body');
            filesTableBody.innerHTML = '';

            // 收集所有文件和目录路径
            const allItems = [];

            checkedItems.forEach(itemPath => {
                // 检查是否是目录
                const isDirectory = isDirectoryPath(itemPath);

                // 检查是否存在
                let exists = true;
                if (isDirectory) {
                    exists = !isPathMissing(data.directories.missing, itemPath) && !isPathMissing(data.missing_files, itemPath);
                } else {
                    exists = !isPathMissing(data.missing_files, itemPath);
                }

                allItems.push({
                    path: itemPath,
                    exists: exists,
                    isDirectory: isDirectory
                });
            });

            // 按路径排序并生成表格行
            allItems.sort((a, b) => a.path.localeCompare(b.path));

            allItems.forEach(item => {
                const row = document.createElement('tr');
                const status = item.exists ? '✅ 完整' : '❌ 缺失';
                const statusClass = item.exists ? 'status-complete' : 'status-incomplete';
                const pathClass = item.exists ? '' : 'missing-file';
                const description = getDescription(item.path);
                const actionHtml = '';

                row.innerHTML = `
                   <td class="${pathClass}">${escapeHtml(item.path)}</td>
                   <td>${escapeHtml(description)}</td>
                   <td class="${statusClass}">${status}</td>
                   <td class="action-cell">${actionHtml}</td>
               `;
                filesTableBody.appendChild(row);
            });

            // 存储当前结果
            currentResult = data;

            // 显示详细结果
            resultDetails.style.display = 'block';

            // 显示或隐藏缺少文件按钮
            if (data.missing_files.length > 0 || data.directories.missing.length > 0) {
                missingBtn.style.display = 'inline-block';
                // 检测到不完整时立即显示一键修复按钮
                if (repairAllBtn) {
                    repairAllBtn.style.display = 'inline-block';
                }
            } else {
                missingBtn.style.display = 'none';
                if (repairAllBtn) {
                    repairAllBtn.style.display = 'none';
                }
            }

            // 生成详细的缺失信息
            let message = '';
            if (data.missing_files.length === 0 && data.directories.missing.length === 0) {
                message = '所有文件和目录都完整';
            } else {
                message = '项目文件目录结构不完整';
            }

            // 使用全局提示框
            callParentToast(message, {
                type: (data.missing_files.length === 0 && data.directories.missing.length === 0) ? 'success' : 'warning'
            });
        }

        function repairItemRequest(path, isDir) {
            return new Promise(function(resolve) {
                const xhr = new XMLHttpRequest();
                xhr.open('POST', '/admin/Plugin.php', true);
                xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
                xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
                xhr.onreadystatechange = function() {
                    if (xhr.readyState !== 4) return;
                    if (xhr.status !== 200) {
                        resolve({ success: false, message: '网络错误' });
                        return;
                    }
                    try {
                        const resp = JSON.parse(xhr.responseText);
                        resolve(resp || { success: false, message: '响应为空' });
                    } catch (e) {
                        resolve({ success: false, message: '响应格式错误' });
                    }
                };
                xhr.send('plugin=31_filecheck&plugin_action=repair_item&path=' + encodeURIComponent(path) + '&is_directory=' + encodeURIComponent(isDir ? 1 : 0));
            });
        }

        function updateRowAfterRepair(path, isDir) {
            const norm = normalizePath(path);
            const row = document.querySelector('#files-table-body .repair-action[data-path="' + cssEscapeCompat(path) + '"]')?.closest('tr');
            if (row) {
                const tds = row.querySelectorAll('td');
                if (tds && tds.length >= 3) {
                    const statusTd = tds[2];
                    statusTd.className = 'status-complete';
                    statusTd.textContent = '✅ 已修复';
                    const pathTd = tds[0];
                    if (pathTd) pathTd.classList.remove('missing-file');
                }
            }

            if (!currentResult) return;
            if (isDir) {
                currentResult.directories.missing = (currentResult.directories.missing || []).filter(p => normalizePath(p) !== norm);
                currentResult.directories.existing = (currentResult.directories.existing || 0) + 1;
            } else {
                currentResult.missing_files = (currentResult.missing_files || []).filter(p => normalizePath(p) !== norm);
                currentResult.existing_files = (currentResult.existing_files || 0) + 1;
            }
            refreshSummaryFromCurrentResult();
        }

        document.getElementById('files-table-body')?.addEventListener('click', function(e) {
            const btn = e.target && e.target.closest ? e.target.closest('.repair-action') : null;
            if (!btn) return;
            if (!currentResult) return;

            const path = btn.getAttribute('data-path') || '';
            const isDir = btn.getAttribute('data-is-dir') === '1' ? 1 : 0;
            if (!path) return;

            btn.disabled = true;

            repairItemRequest(path, isDir).then(function(resp) {
                if (!resp || !resp.success) {
                    btn.disabled = false;
                    callParentToast('修复失败: ' + (resp && (resp.message || resp.error) ? (resp.message || resp.error) : '未知错误'), { type: 'error' });
                    return;
                }

                updateRowAfterRepair(path, !!isDir);

                if ((currentResult.missing_files || []).length === 0 && (currentResult.directories.missing || []).length === 0) {
                    missingBtn.style.display = 'none';
                    if (repairAllBtn) repairAllBtn.style.display = 'none';
                }

                callParentToast(resp.message || '修复成功', { type: 'success' });
            });
        });

        repairAllBtn?.addEventListener('click', async function() {
            if (!currentResult) return;
            const dirs = Array.isArray(currentResult.directories?.missing) ? currentResult.directories.missing.slice() : [];
            const files = Array.isArray(currentResult.missing_files) ? currentResult.missing_files.slice() : [];

            const tasks = [];
            dirs.forEach(p => tasks.push({ path: p, isDir: true }));
            files.forEach(p => tasks.push({ path: p, isDir: isDirectoryPath(p) }));

            if (tasks.length === 0) {
                callParentToast('没有需要修复的项目', { type: 'success' });
                return;
            }

            this.disabled = true;

            let okCount = 0;
            let failCount = 0;
            for (const t of tasks) {
                const resp = await repairItemRequest(t.path, t.isDir ? 1 : 0);
                if (resp && resp.success) {
                    okCount++;
                    updateRowAfterRepair(t.path, t.isDir);
                    const b = document.querySelector('#files-table-body .repair-action[data-path="' + cssEscapeCompat(t.path) + '"]');
                    if (b) b.disabled = true;
                } else {
                    failCount++;
                }
            }

            this.disabled = false;

            if ((currentResult.missing_files || []).length === 0 && (currentResult.directories.missing || []).length === 0) {
                missingBtn.style.display = 'none';
                this.style.display = 'none';
            }

            if (failCount === 0) {
                callParentToast('一键修复完成：全部成功(' + okCount + ')', { type: 'success' });
            } else {
                callParentToast('一键修复完成：成功' + okCount + '，失败' + failCount, { type: 'warning' });
            }
        });
    })();
</script>
