#!/bin/bash

# 配置变量
FILE_DIR="/data/cloudrepo_nginx"
SEARCH_PAGE="/data/cloudrepo_nginx/search.html"
TEMP_FILE="/tmp/search_page.tmp"

echo "开始生成文件索引..."

# 创建HTML文件头部
cat > ${TEMP_FILE} << 'HTML_HEAD'
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>文件搜索 - Linux极客下载站</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.2/font/bootstrap-icons.css" rel="stylesheet">
    <link href="https://cdn.jsdelivr.net/npm/prismjs@1.25.0/themes/prism-tomorrow.min.css" rel="stylesheet">
    <style>
        body { 
            background-color: #f8f9fa;
            transition: overflow 0.3s ease;
        }
        
        /* 滚动锁定 */
        body.modal-open {
            overflow: hidden;
            padding-right: 0;
        }
        
        .search-container { 
            background: white; 
            padding: 2rem; 
            border-radius: 15px; 
            box-shadow: 0 10px 30px rgba(0,0,0,0.1); 
            margin-top: 2rem;
        }
        
        .file-icon {
            width: 45px; 
            height: 45px; 
            border-radius: 10px; 
            display: flex;
            align-items: center; 
            justify-content: center; 
            font-size: 11px;
            font-weight: bold; 
            color: white; 
            margin-right: 15px; 
            flex-shrink: 0;
        }
        
        .icon-shell { background: linear-gradient(45deg, #28a745, #20c997); }
        .icon-python { background: linear-gradient(45deg, #3776ab, #306998); }
        .icon-java { background: linear-gradient(45deg, #f89820, #ed8b00); }
        .icon-go { background: linear-gradient(45deg, #00add8, #007d9c); }
        .icon-javascript { background: linear-gradient(45deg, #f7df1e, #f0db4f); color: #323330 !important; }
        .icon-archive { background: linear-gradient(45deg, #6f42c1, #5a32a3); }
        .icon-text { background: linear-gradient(45deg, #6c757d, #495057); }
        .icon-config { background: linear-gradient(45deg, #fd7e14, #e8590c); }
        .icon-executable { background: linear-gradient(45deg, #343a40, #23272b); }
        .icon-excel { background: linear-gradient(45deg, #217346, #1d5e3f); }
        .icon-default { background: linear-gradient(45deg, #adb5bd, #868e96); }
        
        .file-item { 
            transition: all 0.3s ease; 
            padding: 15px; 
            border-radius: 10px; 
            border: 1px solid #e9ecef; 
            margin-bottom: 10px;
            background: white;
        }
        
        .file-item:hover { 
            background-color: #f8f9fa; 
            transform: translateY(-2px); 
            box-shadow: 0 4px 15px rgba(0,0,0,0.1);
        }
        
        .category-header { 
            color: #0d6efd; 
            border-left: 4px solid #0d6efd; 
            padding-left: 15px; 
            margin-bottom: 20px;
            background: linear-gradient(90deg, #f8f9ff 0%, transparent 100%);
            padding: 15px; 
            border-radius: 5px;
        }
        
        .file-name a { 
            color: #333; 
            text-decoration: none; 
            font-weight: 500;
        }
        
        .file-name a:hover { 
            color: #0d6efd; 
        }
        
        .btn-home {
            background: linear-gradient(45deg, #0d6efd, #007bff);
            border: none; 
            color: white;
        }
        
        .search-input { 
            border-radius: 10px; 
            border: 2px solid #e9ecef; 
        }
        
        .search-input:focus { 
            border-color: #0d6efd; 
            box-shadow: 0 0 0 0.2rem rgba(13,110,253,0.25); 
        }
        
        .file-actions {
            display: flex;
            gap: 8px;
            align-items: center;
            flex-wrap: wrap;
        }
        
        .btn-action {
            padding: 6px 12px;
            border-radius: 6px;
            font-size: 12px;
            text-decoration: none;
            display: inline-flex;
            align-items: center;
            gap: 4px;
            transition: all 0.3s ease;
            border: none;
            cursor: pointer;
            white-space: nowrap;
        }
        
        .btn-action:disabled {
            opacity: 0.6;
            cursor: not-allowed;
            transform: none !important;
        }
        
        .btn-download {
            background: #28a745;
            color: white;
        }
        
        .btn-download:hover:not(:disabled) {
            background: #218838;
            color: white;
            transform: translateY(-1px);
        }
        
        .btn-folder {
            background: #17a2b8;
            color: white;
        }
        
        .btn-folder:hover:not(:disabled) {
            background: #138496;
            color: white;
            transform: translateY(-1px);
        }
        
        .btn-preview {
            background: #ffc107;
            color: #212529;
        }
        
        .btn-preview:hover:not(:disabled) {
            background: #e0a800;
            color: #212529;
            transform: translateY(-1px);
        }
        
        .btn-preview.loading {
            background: #6c757d;
            color: white;
        }
        
        .file-path {
            font-family: 'Courier New', monospace;
            font-size: 11px;
            color: #6c757d;
            background: #f8f9fa;
            padding: 2px 6px;
            border-radius: 3px;
            margin-top: 4px;
            word-break: break-all;
        }

        /* 回到顶部按钮 */
        .back-to-top {
            position: fixed;
            bottom: 30px;
            right: 30px;
            background: linear-gradient(45deg, #0d6efd, #007bff);
            color: white;
            border: none;
            border-radius: 50%;
            width: 50px;
            height: 50px;
            opacity: 0;
            visibility: hidden;
            display: flex;
            align-items: center;
            justify-content: center;
            box-shadow: 0 4px 15px rgba(0,0,0,0.2);
            transition: all 0.3s ease;
            z-index: 1000;
        }
        
        .back-to-top:hover {
            background: linear-gradient(45deg, #0b5ed7, #0056b3);
            transform: translateY(-2px);
        }
        
        .back-to-top.show {
            opacity: 1;
            visibility: visible;
        }

        /* 预览模态框 */
        .preview-modal {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0,0,0,0.8);
            z-index: 2000;
            opacity: 0;
            visibility: hidden;
            transition: all 0.3s ease;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        
        .preview-modal.show {
            opacity: 1;
            visibility: visible;
        }
        
        .preview-content {
            background: white;
            border-radius: 15px;
            width: 90%;
            max-width: 900px;
            max-height: 85vh;
            overflow: hidden;
            display: flex;
            flex-direction: column;
            box-shadow: 0 20px 60px rgba(0,0,0,0.3);
            transform: translateY(20px) scale(0.95);
            transition: all 0.3s ease;
        }
        
        .preview-modal.show .preview-content {
            transform: translateY(0) scale(1);
        }
        
        .preview-header {
            padding: 20px;
            background: #f8f9fa;
            border-bottom: 1px solid #dee2e6;
            display: flex;
            justify-content: space-between;
            align-items: center;
            flex-shrink: 0;
            border-radius: 15px 15px 0 0;
        }
        
        .preview-body {
            flex: 1;
            overflow: hidden;
            display: flex;
            flex-direction: column;
            min-height: 0;
        }
        
        .preview-content-wrapper {
            flex: 1;
            overflow-y: auto;
            overflow-x: auto;
        }
        
        .preview-code {
            background: #2d3748 !important;
            color: #e2e8f0;
            padding: 20px;
            margin: 0;
            font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
            font-size: 13px;
            line-height: 1.6;
            white-space: pre;
            min-height: 100%;
            border: none;
        }
        
        .preview-text {
            padding: 20px;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            line-height: 1.6;
            white-space: pre-wrap;
            word-wrap: break-word;
        }
        
        .close-preview {
            background: none;
            border: none;
            font-size: 24px;
            color: #6c757d;
            cursor: pointer;
            padding: 8px;
            width: 40px;
            height: 40px;
            display: flex;
            align-items: center;
            justify-content: center;
            border-radius: 50%;
            transition: all 0.3s ease;
        }
        
        .close-preview:hover {
            color: #dc3545;
            background: rgba(220, 53, 69, 0.1);
        }

        .loading-spinner {
            text-align: center;
            padding: 40px 20px;
        }

        .error-message {
            text-align: center;
            padding: 40px 20px;
        }

        .no-results {
            text-align: center;
            padding: 60px 20px;
            color: #6c757d;
        }

        /* 响应式设计 */
        @media (max-width: 768px) {
            .preview-content {
                width: 95%;
                max-height: 90vh;
                border-radius: 10px;
            }
            .preview-header {
                border-radius: 10px 10px 0 0;
                padding: 15px;
            }
            .file-actions {
                flex-direction: column;
                gap: 4px;
            }
            .btn-action {
                width: 100%;
                justify-content: center;
            }
        }
    </style>
</head>
<body>
    <div class="container my-4">
        <div class="search-container">
            <div class="d-flex justify-content-between align-items-center mb-4">
                <div>
                    <h1 class="text-primary mb-1">🔍 文件搜索</h1>
                    <p class="text-muted mb-0">快速查找您需要的脚本和文件</p>
                </div>
                <a href="/" class="btn btn-home px-4">← 返回首页</a>
            </div>
            
            <div class="input-group mb-4">
                <span class="input-group-text">🔍</span>
                <input type="text" class="form-control form-control-lg search-input" id="searchInput" 
                       placeholder="输入文件名、扩展名或关键词进行搜索..." />
            </div>
            
            <div class="alert alert-info" id="fileStats">正在加载文件...</div>
            
            <div id="fileList">
                <div class="loading-spinner">
                    <div class="spinner-border text-primary mb-3" role="status"></div>
                    <p>正在加载文件列表...</p>
                </div>
            </div>
        </div>
    </div>

    <!-- 回到顶部按钮 -->
    <button class="back-to-top" id="backToTop" type="button" title="回到顶部">
        <i class="bi bi-arrow-up"></i>
    </button>

    <!-- 预览模态框 -->
    <div class="preview-modal" id="previewModal" role="dialog" aria-hidden="true" aria-labelledby="previewTitle">
        <div class="preview-content" role="document">
            <div class="preview-header">
                <h5 id="previewTitle" class="mb-0">文件预览</h5>
                <button class="close-preview" type="button" aria-label="关闭预览">
                    <i class="bi bi-x"></i>
                </button>
            </div>
            <div class="preview-body">
                <div class="preview-content-wrapper" id="previewBody">
                    <div class="loading-spinner">
                        <div class="spinner-border text-primary" role="status"></div>
                        <p class="mt-2 text-muted">准备加载...</p>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/prismjs@1.25.0/components/prism-core.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/prismjs@1.25.0/plugins/autoloader/prism-autoloader.min.js"></script>
    <script>
        // 文件数据
        const filesData = [
HTML_HEAD

echo "正在扫描文件..."

# 初始化计数器
file_count=0

# 扫描文件并生成索引
while IFS= read -r file; do
    if [[ "$(basename "$file")" != "search.html" ]]; then
        filename=$(basename "$file")
        relative_path=${file#${FILE_DIR}}
        
        # 获取目录路径（去掉文件名）
        dir_path=$(dirname "$relative_path")
        if [[ "$dir_path" == "." ]]; then
            dir_path="/"
        fi
        
        size=$(du -h "$file" 2>/dev/null | cut -f1 || echo "未知")
        modified=$(ls -l "$file" 2>/dev/null | awk '{print $6" "$7" "$8}' || echo "未知")
        
        # 判断是否可预览
        extension="${filename##*.}"
        can_preview="false"
        case "$extension" in
            sh|py|js|java|go|txt|md|json|xml|yml|yaml|conf|cfg|ini|log|csv|html|css|sql|dockerfile) 
                can_preview="true" 
                ;;
        esac
        
        # 确定文件类型和分类
        if [[ "$file" == *"/docker部署/"* ]]; then
            category="Docker部署"
            filetype="Docker配置"
        elif [[ "$file" == *"/项目源码/"* ]]; then
            category="项目源码"
            filetype=$(echo "$filename" | rev | cut -d'.' -f1 | rev | tr '[:lower:]' '[:upper:]')
        elif [[ "$file" == *"/软件包/"* ]]; then
            category="软件包"
            filetype=$(echo "$filename" | rev | cut -d'.' -f1 | rev | tr '[:lower:]' '[:upper:]')
        else
            case "$extension" in
                sh) category="Shell脚本"; filetype="Shell脚本" ;;
                py) category="Python脚本"; filetype="Python脚本" ;;
                java) category="Java源码"; filetype="Java源码" ;;
                go) category="Go源码"; filetype="Go源码" ;;
                js) category="JavaScript"; filetype="JavaScript" ;;
                txt|md) category="文本文件"; filetype="文本文件" ;;
                xlsx|xls) category="Excel表格"; filetype="Excel表格" ;;
                csv) category="CSV数据"; filetype="CSV数据" ;;
                conf|cfg|ini|json) category="配置文件"; filetype="配置文件" ;;
                xml) category="XML文件"; filetype="XML文件" ;;
                yml|yaml) category="YAML配置"; filetype="YAML配置" ;;
                zip|rar|gz|tar) category="压缩文件"; filetype="压缩文件" ;;
                deb) category="Debian包"; filetype="Debian包" ;;
                rpm) category="RPM包"; filetype="RPM包" ;;
                exe|msi|bin|run) category="可执行文件"; filetype="可执行文件" ;;
                log) category="日志文件"; filetype="日志文件" ;;
                html) category="网页文件"; filetype="HTML文件" ;;
                css) category="样式文件"; filetype="CSS文件" ;;
                sql) category="数据库文件"; filetype="SQL文件" ;;
                dockerfile) category="Docker文件"; filetype="Dockerfile" ;;
                *) category="其他文件"; filetype="其他文件" ;;
            esac
        fi
        
        # 转义特殊字符
        filename_escaped=$(echo "$filename" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g')
        relative_path_escaped=$(echo "$relative_path" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g')
        dir_path_escaped=$(echo "$dir_path" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g')
        
        echo "            {" >> ${TEMP_FILE}
        echo "                \"name\": \"$filename_escaped\"," >> ${TEMP_FILE}
        echo "                \"path\": \"$relative_path_escaped\"," >> ${TEMP_FILE}
        echo "                \"dir_path\": \"$dir_path_escaped\"," >> ${TEMP_FILE}
        echo "                \"size\": \"$size\"," >> ${TEMP_FILE}
        echo "                \"type\": \"$filetype\"," >> ${TEMP_FILE}
        echo "                \"category\": \"$category\"," >> ${TEMP_FILE}
        echo "                \"modified\": \"$modified\"," >> ${TEMP_FILE}
        echo "                \"can_preview\": $can_preview" >> ${TEMP_FILE}
        echo "            }," >> ${TEMP_FILE}
        
        ((file_count++))
    fi
done < <(find "${FILE_DIR}" -type f 2>/dev/null)

# 移除最后一个逗号
if [[ $file_count -gt 0 ]]; then
    sed -i '$ s/,$//' ${TEMP_FILE}
fi

# 添加HTML尾部
cat >> ${TEMP_FILE} << 'HTML_TAIL'
        ];

        // 全局状态
        let appState = {
            isModalOpen: false,
            isLoading: false,
            currentRequest: null,
            initialized: false
        };

        // 工具函数
        function debounce(func, wait) {
            let timeout;
            return function executedFunction(...args) {
                const later = () => {
                    clearTimeout(timeout);
                    func(...args);
                };
                clearTimeout(timeout);
                timeout = setTimeout(later, wait);
            };
        }

        function escapeHtml(text) {
            const div = document.createElement('div');
            div.textContent = text;
            return div.innerHTML;
        }

        function getFileIcon(filename) {
            const ext = filename.split('.').pop().toLowerCase();
            const iconMap = {
                'sh': 'icon-shell',
                'py': 'icon-python',
                'java': 'icon-java',
                'go': 'icon-go',
                'js': 'icon-javascript',
                'xlsx': 'icon-excel',
                'xls': 'icon-excel',
                'zip': 'icon-archive',
                'rar': 'icon-archive',
                'gz': 'icon-archive',
                'tar': 'icon-archive',
                'txt': 'icon-text',
                'md': 'icon-text',
                'log': 'icon-text',
                'html': 'icon-text',
                'css': 'icon-text',
                'sql': 'icon-text',
                'conf': 'icon-config',
                'cfg': 'icon-config',
                'ini': 'icon-config',
                'json': 'icon-config',
                'yml': 'icon-config',
                'yaml': 'icon-config',
                'exe': 'icon-executable',
                'msi': 'icon-executable',
                'bin': 'icon-executable',
                'run': 'icon-executable'
            };
            return iconMap[ext] || 'icon-default';
        }

        function getFileExtension(filename) {
            const ext = filename.split('.').pop().toLowerCase();
            return ext.length > 4 ? ext.substring(0, 4).toUpperCase() : ext.toUpperCase();
        }

        function getLanguageForPrism(ext) {
            const langMap = {
                'sh': 'bash',
                'py': 'python',
                'js': 'javascript',
                'java': 'java',
                'go': 'go',
                'json': 'json',
                'xml': 'xml',
                'yml': 'yaml',
                'yaml': 'yaml',
                'html': 'html',
                'css': 'css',
                'sql': 'sql',
                'conf': 'nginx',
                'cfg': 'nginx',
                'dockerfile': 'docker'
            };
            return langMap[ext] || 'text';
        }

        // 搜索功能
        function searchFiles() {
            console.log('开始搜索...');
            
            try {
                const searchTerm = document.getElementById('searchInput').value.toLowerCase().trim();
                const fileListContainer = document.getElementById('fileList');
                const fileStatsElement = document.getElementById('fileStats');
                
                console.log('搜索词:', searchTerm);
                console.log('文件总数:', filesData.length);
                
                // 过滤文件
                const filteredFiles = filesData.filter(file => {
                    if (!file || typeof file !== 'object') return false;
                    
                    const searchableText = [
                        file.name || '',
                        file.type || '',
                        file.category || '',
                        file.path || ''
                    ].join(' ').toLowerCase();
                    
                    return searchableText.includes(searchTerm);
                });

                console.log('找到匹配文件:', filteredFiles.length);

                // 更新统计信息
                fileStatsElement.innerHTML = 
                    `共 <strong>${filesData.length}</strong> 个文件` + 
                    (searchTerm ? `，找到 <strong>${filteredFiles.length}</strong> 个匹配项` : '');

                // 清空容器
                fileListContainer.innerHTML = '';

                // 如果没有找到文件
                if (filteredFiles.length === 0) {
                    fileListContainer.innerHTML = `
                        <div class="no-results">
                            <div style="font-size: 4rem;">🔍</div>
                            <h3 class="mt-3">未找到匹配的文件</h3>
                            <p>请尝试其他关键词</p>
                        </div>
                    `;
                    return;
                }

                // 按类别分组
                const grouped = {};
                filteredFiles.forEach(file => {
                    const category = file.category || '其他文件';
                    if (!grouped[category]) {
                        grouped[category] = [];
                    }
                    grouped[category].push(file);
                });

                console.log('分组结果:', Object.keys(grouped));

                // 渲染文件列表
                Object.keys(grouped).sort().forEach(category => {
                    const categoryFiles = grouped[category];
                    
                    // 创建分类标题
                    const section = document.createElement('div');
                    section.className = 'mb-4';
                    
                    const categoryHeader = document.createElement('div');
                    categoryHeader.className = 'category-header';
                    categoryHeader.innerHTML = `
                        <h4 class="mb-0">${category} 
                            <span class="badge bg-primary ms-2">${categoryFiles.length}</span>
                        </h4>
                    `;
                    section.appendChild(categoryHeader);

                    // 渲染文件项
                    categoryFiles.forEach(file => {
                        const fileItem = createFileItem(file);
                        section.appendChild(fileItem);
                    });

                    fileListContainer.appendChild(section);
                });

                console.log('文件列表渲染完成');
                
            } catch (error) {
                console.error('搜索出错:', error);
                document.getElementById('fileList').innerHTML = `
                    <div class="error-message">
                        <div class="alert alert-danger">
                            <i class="bi bi-exclamation-triangle me-2"></i>
                            搜索时发生错误：${error.message}
                        </div>
                    </div>
                `;
            }
        }

        function createFileItem(file) {
            const fileItem = document.createElement('div');
            fileItem.className = 'file-item d-flex align-items-center justify-content-between';
            
            const previewButton = file.can_preview ? 
                `<button class="btn-action btn-preview" onclick="previewFile('${file.path}', '${file.name}')" title="预览文件" type="button">
                    <i class="bi bi-eye"></i> 预览
                </button>` : '';
            
            fileItem.innerHTML = `
                <div class="d-flex align-items-center flex-grow-1">
                    <div class="file-icon ${getFileIcon(file.name)}">
                        ${getFileExtension(file.name)}
                    </div>
                    <div class="flex-grow-1">
                        <div class="file-name">
                            <strong>${escapeHtml(file.name)}</strong>
                        </div>
                        <small class="text-muted">
                            ${escapeHtml(file.type)} • ${escapeHtml(file.size)} • ${escapeHtml(file.modified)}
                        </small>
                        <div class="file-path">📁 ${escapeHtml(file.dir_path)}</div>
                    </div>
                </div>
                <div class="file-actions">
                    ${previewButton}
                    <a href="${escapeHtml(file.path)}" class="btn-action btn-download" title="下载文件">
                        <i class="bi bi-download"></i> 下载
                    </a>
                    <a href="${escapeHtml(file.dir_path)}" class="btn-action btn-folder" title="查看目录">
                        <i class="bi bi-folder2-open"></i> 目录
                    </a>
                </div>
            `;
            
            return fileItem;
        }

        // 预览功能
        function previewFile(filePath, fileName) {
            if (appState.isLoading) {
                console.log('已有文件正在加载中，忽略此次请求');
                return;
            }

            console.log('开始预览文件:', fileName);
            appState.isLoading = true;

            const modal = document.getElementById('previewModal');
            const title = document.getElementById('previewTitle');
 const body = document.getElementById('previewBody');
            
            title.textContent = `预览: ${fileName}`;
            body.innerHTML = `
                <div class="loading-spinner">
                    <div class="spinner-border text-primary" role="status"></div>
                    <p class="mt-2 text-muted">正在加载文件...</p>
                </div>
            `;
            
            openModal();

            // 取消之前的请求
            if (appState.currentRequest) {
                appState.currentRequest.abort();
            }

            // 创建新的请求
            appState.currentRequest = new AbortController();
            
            fetch(filePath, { 
                signal: appState.currentRequest.signal,
                cache: 'no-cache'
            })
            .then(response => {
                if (!response.ok) {
                    throw new Error(`HTTP ${response.status}: ${response.statusText}`);
                }
                return response.text();
            })
            .then(content => {
                if (appState.currentRequest.signal.aborted) {
                    return;
                }

                const ext = fileName.split('.').pop().toLowerCase();
                
                // 限制文件大小
                if (content.length > 1000000) { // 1MB
                    const truncated = content.substring(0, 1000000);
                    content = truncated + '\n\n... (文件过大，已截断显示，仅显示前1MB内容)';
                }

                const escapedContent = escapeHtml(content);
                const codeExtensions = ['sh', 'py', 'js', 'java', 'go', 'json', 'xml', 'yml', 'yaml', 'html', 'css', 'sql', 'conf', 'cfg', 'dockerfile'];
                
                if (codeExtensions.includes(ext)) {
                    const language = getLanguageForPrism(ext);
                    body.innerHTML = `<pre class="preview-code"><code class="language-${language}">${escapedContent}</code></pre>`;
                    
                    // 延迟执行语法高亮
                    setTimeout(() => {
                        if (window.Prism) {
                            Prism.highlightAll();
                        }
                    }, 10);
                } else {
                    body.innerHTML = `<div class="preview-text">${escapedContent.replace(/\n/g, '<br>')}</div>`;
                }
            })
            .catch(error => {
                if (error.name === 'AbortError') {
                    console.log('请求被取消');
                    return;
                }
                console.error('文件加载失败:', error);
                body.innerHTML = `
                    <div class="error-message">
                        <div class="alert alert-danger">
                            <i class="bi bi-exclamation-triangle me-2"></i>
                            加载失败: ${error.message}
                        </div>
                    </div>
                `;
            })
            .finally(() => {
                appState.isLoading = false;
                appState.currentRequest = null;
            });
        }

        function openModal() {
            if (appState.isModalOpen) return;
            
            appState.isModalOpen = true;
            document.body.classList.add('modal-open');
            document.getElementById('previewModal').classList.add('show');
        }

        function closeModal() {
            if (!appState.isModalOpen) return;
            
            // 取消正在进行的请求
            if (appState.currentRequest) {
                appState.currentRequest.abort();
                appState.currentRequest = null;
            }
            
            appState.isModalOpen = false;
            appState.isLoading = false;
            
            document.body.classList.remove('modal-open');
            document.getElementById('previewModal').classList.remove('show');
        }

        // 回到顶部功能
        function initBackToTop() {
            const backToTopBtn = document.getElementById('backToTop');
            
            window.addEventListener('scroll', debounce(() => {
                if (window.pageYOffset > 300) {
                    backToTopBtn.classList.add('show');
                } else {
                    backToTopBtn.classList.remove('show');
                }
            }, 100));
            
            backToTopBtn.addEventListener('click', () => {
                window.scrollTo({
                    top: 0,
                    behavior: 'smooth'
                });
            });
        }

        // 初始化应用
        function initApp() {
            if (appState.initialized) {
                console.warn('应用已经初始化，跳过重复初始化');
                return;
            }

            console.log('初始化应用...');
            console.log('文件数据:', filesData.length, '个文件');
            
            try {
                // 绑定搜索事件
                const searchInput = document.getElementById('searchInput');
                if (searchInput) {
                    searchInput.addEventListener('input', debounce(searchFiles, 300));
                }
                
                // 绑定模态框关闭事件
                const closeBtn = document.querySelector('.close-preview');
                if (closeBtn) {
                    closeBtn.addEventListener('click', closeModal);
                }
                
                const modal = document.getElementById('previewModal');
                if (modal) {
                    modal.addEventListener('click', (e) => {
                        if (e.target === modal) {
                            closeModal();
                        }
                    });
                }
                
                // 初始化回到顶部
                initBackToTop();
                
                // 键盘快捷键
                document.addEventListener('keydown', (e) => {
                    if (e.key === '/' && e.target.tagName !== 'INPUT') {
                        e.preventDefault();
                        searchInput.focus();
                    }
                    if (e.key === 'Escape' && appState.isModalOpen) {
                        closeModal();
                    }
                });
                
                // 初始化搜索
                searchFiles();
                
                // 聚焦搜索框
                if (searchInput) {
                    searchInput.focus();
                }
                
                appState.initialized = true;
                console.log('应用初始化完成');
                
            } catch (error) {
                console.error('应用初始化失败:', error);
                document.getElementById('fileList').innerHTML = `
                    <div class="error-message">
                        <div class="alert alert-danger">
                            <i class="bi bi-exclamation-triangle me-2"></i>
                            应用初始化失败：${error.message}
                        </div>
                    </div>
                `;
            }
        }

        // 页面加载完成后初始化
        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', initApp);
        } else {
            initApp();
        }

        // 页面卸载时清理
        window.addEventListener('beforeunload', () => {
            if (appState.currentRequest) {
                appState.currentRequest.abort();
            }
        });
    </script>
</body>
</html>
HTML_TAIL

# 移动文件并设置权限
mv ${TEMP_FILE} ${SEARCH_PAGE}
chmod 644 ${SEARCH_PAGE}

echo "文件索引生成完成!"
echo "生成了 $file_count 个文件的索引"
echo "搜索页面: $SEARCH_PAGE"
