<!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=no">
    <title>JSON 编辑器</title>
    <script type="importmap">
    {
        "imports": {
            "vue": "/static/lib/vue.esm-browser.js"
        }
    }
    </script>
    <style>
        * { box-sizing: border-box; margin: 0; padding: 0; }
        html, body, #app { width: 100%; height: 100%; overflow: hidden; }
        body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #f6f8fa; }
        
        .header { 
            display: flex; align-items: center; justify-content: space-between;
            padding: 12px 16px; background: #fff; border-bottom: 1px solid #d0d7de;
            height: 56px;
        }
        .header-title { font-size: 16px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 200px; }
        .header-actions { display: flex; gap: 8px; }
        
        .btn {
            padding: 8px 16px; border-radius: 8px; border: none; font-size: 14px;
            cursor: pointer; display: flex; align-items: center; gap: 4px;
        }
        .btn-primary { background: #2da44e; color: #fff; }
        .btn-secondary { background: #f3f4f6; color: #24292f; }
        .btn:disabled { opacity: 0.5; cursor: not-allowed; }
        
        .editor-container { height: calc(100vh - 56px); position: relative; }
        .editor-wrapper { height: 100%; }
        
        .status-bar {
            position: fixed; bottom: 0; left: 0; right: 0;
            padding: 8px 16px; font-size: 12px;
            display: flex; justify-content: space-between;
            z-index: 100;
        }
        .status-success { background: #dafbe1; color: #1a7f37; }
        .status-error { background: #ffebe9; color: #cf222e; }
        .status-saving { background: #fff8c5; color: #9a6700; }
        
        .loading-overlay {
            position: fixed; inset: 0; background: rgba(255,255,255,0.95);
            display: flex; flex-direction: column; align-items: center; justify-content: center;
            z-index: 1000;
        }
        .spinner {
            width: 40px; height: 40px; border: 3px solid #e1e4e8;
            border-top-color: #0969da; border-radius: 50%;
            animation: spin 0.8s linear infinite;
        }
        @keyframes spin { to { transform: rotate(360deg); } }
        .loading-text { margin-top: 12px; color: #666; font-size: 14px; }
        
        .error-message {
            padding: 20px; color: #cf222e; text-align: center;
        }
    </style>
</head>
<body>
    <div id="app">
        <div v-if="loading" class="loading-overlay">
            <div class="spinner"></div>
            <div class="loading-text">{{ loadingText }}</div>
        </div>
        
        <template v-else>
            <div class="header">
                <div style="display:flex;flex-direction:column;gap:2px;overflow:hidden;">
                    <div class="header-title">{{ filename }}</div>
                    <div style="font-size:11px;color:#666;">{{ filepath }}</div>
                </div>
                <div class="header-actions">
                    <button class="btn btn-primary" @click="saveJson" :disabled="!changed">保存</button>
                </div>
            </div>
            
            <div v-if="loadError" class="editor-container">
                <div class="error-message">{{ loadError }}</div>
            </div>
            
            <div v-else class="editor-container">
                <div ref="editorRef" class="editor-wrapper"></div>
            </div>
            
            <div v-if="status" class="status-bar" :class="statusClass">
                {{ status }}
                <span v-if="lastSaved">保存于 {{ lastSaved }}</span>
            </div>
        </template>
    </div>

    <script type="module">
    import { createApp, ref, computed, watch, onMounted, onBeforeUnmount, nextTick } from 'vue'
    
    const filepath = new URLSearchParams(window.location.search).get('path') || ''
    const filename = filepath.split('/').pop() || 'untitled.json'
    
    let editor = null
    
    const app = createApp({
        setup() {
            const loading = ref(true)
            const loadingText = ref('加载中...')
            const loadError = ref('')
            const jsonContent = ref({})
            const changed = ref(false)
            const status = ref('')
            const lastSaved = ref('')
            const editorRef = ref(null)
            
            const statusClass = computed(() => {
                if (status.value.includes('成功')) return 'status-success'
                if (status.value.includes('失败') || status.value.includes('错误')) return 'status-error'
                if (status.value.includes('保存中') || status.value.includes('已修改')) return 'status-saving'
                return ''
            })
            
            const loadFile = async () => {
                try {
                    loadingText.value = '加载文件...'
                    
                    // 检测是否为 FRP 配置文件
                    const isFrpConfig = filepath.includes('/usr/local/frp/frpc.toml')
                    const apiUrl = isFrpConfig ? '/api/frp/config' : '/api/file/read?path=' + encodeURIComponent(filepath)
                    
                    const response = await fetch(apiUrl)
                    const data = await response.json()
                    
                    if (data.success && data.data) {
                        try {
                            const content = data.data.content || data.data || '{}'
                            const parsed = JSON.parse(content)
                            jsonContent.value = parsed
                            loading.value = false
                            await nextTick()
                            initEditor(parsed)
                            showStatus('已加载')
                        } catch (e) {
                            loadingText.value = 'JSON解析失败: ' + e.message
                            loadError.value = 'JSON解析失败: ' + e.message
                            loading.value = false
                        }
                    } else {
                        loadingText.value = '加载失败: ' + (data.error || '未知错误')
                        loadError.value = '加载失败: ' + (data.error || '未知错误')
                        loading.value = false
                    }
                } catch (e) {
                    loadingText.value = '加载失败: ' + e.message
                    loadError.value = '加载失败: ' + e.message
                    loading.value = false
                }
            }
            
            const initEditor = async (content) => {
                // Dynamically import vanilla-jsoneditor
                const module = await import('/static/lib/vanilla-jsoneditor/index.js')
                
                if (!editorRef.value) return
                
                editor = new module.JSONEditor({
                    target: editorRef.value,
                    props: {
                        content: { json: content },
                        mode: 'tree',
                        mainMenuBar: false,
                        statusBar: false,
                        navigationBar: true,
                        onChange: (updatedContent, patchResult) => {
                            if (!loading.value) {
                                changed.value = true
                                status.value = '已修改'
                            }
                        }
                    }
                })
            }
            
            const showStatus = (msg) => {
                status.value = msg
                setTimeout(() => {
                    if (status.value === msg) status.value = ''
                }, 3000)
            }
            
            const saveJson = async () => {
                try {
                    if (!editor) return
                    
                    status.value = '保存中...'
                    
                    // Get current content from editor
                    const content = editor.get().json
                    const contentStr = JSON.stringify(content, null, 2)
                    
                    // 检测是否为 FRP 配置文件
                    const isFrpConfig = filepath.includes('/usr/local/frp/frpc.toml')
                    
                    let response, data
                    if (isFrpConfig) {
                        response = await fetch('/api/frp/config', {
                            method: 'POST',
                            headers: { 'Content-Type': 'application/json' },
                            body: JSON.stringify({ content: contentStr })
                        })
                        data = await response.json()
                    } else {
                        response = await fetch('/api/file/save', {
                            method: 'POST',
                            headers: { 'Content-Type': 'application/json' },
                            body: JSON.stringify({
                                path: filepath,
                                content: contentStr,
                                format: 'json'
                            })
                        })
                        data = await response.json()
                    }
                    
                    if (data.success) {
                        changed.value = false
                        lastSaved.value = new Date().toLocaleTimeString()
                        status.value = '保存成功!'
                    } else {
                        status.value = '保存失败: ' + (data.error || '未知错误')
                    }
                } catch (e) {
                    status.value = '保存失败: ' + e.message
                }
            }
            
            const formatJson = () => {
                if (!editor) return
                const content = editor.get().json
                editor.set({ json: content })
                changed.value = true
                status.value = '已格式化'
            }
            
            const compactJson = () => {
                if (!editor) return
                const content = editor.get().json
                editor.set({ json: content })
                // Compact mode - single line
                editor.set({ json: content }) // Will be re-formatted by editor
                changed.value = true
                status.value = '已压缩'
            }
            
            onBeforeUnmount(() => {
                if (editor) {
                    editor.destroy()
                    editor = null
                }
            })
            
            onMounted(() => {
                loadFile()
            })
            
            return {
                filename,
                filepath,
                loading,
                loadingText,
                loadError,
                jsonContent,
                changed,
                status,
                lastSaved,
                statusClass,
                editorRef,
                saveJson,
                formatJson,
                compactJson
            }
        }
    })
    
    app.mount('#app')
    </script>
</body>
</html>
