<template>
  <div class="config-page">
    <!-- Header card -->
    <div class="card animate-in">
      <div class="card-head">
        <h3>系统配置</h3>
        <el-button type="primary" size="small" :loading="saving" @click="saveAll">
          保存所有修改
        </el-button>
      </div>

      <div class="config-layout">
        <!-- Section sidebar -->
        <div class="section-nav">
          <button
            v-for="(_, name) in config"
            :key="name"
            class="section-btn"
            :class="{ active: activeTab === name }"
            @click="activeTab = name"
          >
            <el-icon :size="16"><Setting /></el-icon>
            <span>{{ sectionLabels[name] || name }}</span>
          </button>
        </div>

        <!-- Config fields -->
        <div class="config-fields">
          <div v-if="!activeTab" class="empty-state">
            <svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="#d1d5db" stroke-width="1">
              <circle cx="12" cy="12" r="3"/>
              <path d="M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 010 2.83 2 2 0 01-2.83 0l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-2 2 2 2 0 01-2-2v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83 0 2 2 0 010-2.83l.06-.06A1.65 1.65 0 004.68 15a1.65 1.65 0 00-1.51-1H3a2 2 0 01-2-2 2 2 0 012-2h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 010-2.83 2 2 0 012.83 0l.06.06A1.65 1.65 0 009 4.68a1.65 1.65 0 001-1.51V3a2 2 0 012-2 2 2 0 012 2v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 0 2 2 0 010 2.83l-.06.06A1.65 1.65 0 0019.4 9a1.65 1.65 0 001.51 1H21a2 2 0 012 2 2 2 0 01-2 2h-.09a1.65 1.65 0 00-1.51 1z"/>
            </svg>
            <p>选择左侧配置分类</p>
          </div>

          <div v-else class="field-list">
            <div
              v-for="(value, key) in config[activeTab]"
              :key="key"
              class="field-row"
              :class="{ edited: isEdited(activeTab, key, value) }"
            >
              <label class="field-label">
                {{ key }}
                <span v-if="isEdited(activeTab, key, value)" class="edited-dot"></span>
              </label>
              <el-input
                v-if="isSensitive(key)"
                :model-value="edited[activeTab]?.[key] ?? ''"
                @update:model-value="setEditedValue(activeTab, key, $event)"
                placeholder="已设置，留空保持不变"
                size="small"
                show-password
              />
              <el-input
                v-else
                :model-value="getEditedValue(activeTab, key, value)"
                @update:model-value="setEditedValue(activeTab, key, $event)"
                size="small"
              />
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { Setting } from '@element-plus/icons-vue'
import api from '../api'

const loading = ref(false)
const saving = ref(false)
const activeTab = ref('')
const config = ref<Record<string, Record<string, string>>>({})
const edited = reactive<Record<string, Record<string, string>>>({})

const sectionLabels: Record<string, string> = {
  API: 'API 配置',
  Paths: '路径设置',
  Performance: '性能参数',
  File: '文件设置',
  Templates: '模板配置',
  Gitea: 'Gitea 同步',
  WebAuth: 'Web 认证',
}

const SENSITIVE_KEYS = new Set(['api_key', 'secret_key', 'token', 'password', 'api_secret', 'access_key'])

function isSensitive(key: string): boolean {
  return SENSITIVE_KEYS.has(key.toLowerCase())
}

function isEdited(section: string, key: string, original: string): boolean {
  const val = edited[section]?.[key]
  if (val === undefined) return false
  if (isSensitive(key)) return val !== ''
  return val !== original
}

async function loadConfig() {
  loading.value = true
  try {
    const res = await api.get('/config')
    config.value = res.data
    const keys = Object.keys(res.data)
    if (keys.length > 0 && !activeTab.value) {
      activeTab.value = keys[0]
    }
  } catch {
    ElMessage.error('加载配置失败')
  } finally {
    loading.value = false
  }
}

function getEditedValue(section: string, key: string, original: string): string {
  return edited[section]?.[key] ?? original
}

function setEditedValue(section: string, key: string, value: string) {
  if (!edited[section]) edited[section] = {}
  edited[section][key] = value
}

async function saveAll() {
  const updates: { section: string; key: string; value: string }[] = []
  for (const [section, keys] of Object.entries(edited)) {
    for (const [key, value] of Object.entries(keys)) {
      // Skip empty sensitive fields (user left placeholder unchanged)
      if (isSensitive(key) && !value) continue
      // Skip masked values that somehow got through
      if (isSensitive(key) && value.includes('*')) continue
      updates.push({ section, key, value })
    }
  }

  if (updates.length === 0) {
    ElMessage.info('没有修改')
    return
  }

  saving.value = true
  try {
    await api.put('/config/bulk', { updates })
    ElMessage.success(`已保存 ${updates.length} 项配置`)
    for (const key of Object.keys(edited)) {
      delete edited[key]
    }
    loadConfig()
  } catch (err: any) {
    ElMessage.error(err.response?.data?.detail || '保存失败')
  } finally {
    saving.value = false
  }
}

onMounted(loadConfig)
</script>

<style scoped>
.config-page {
  max-width: 1200px;
}

/* ── Card ── */
.card {
  background: #fff;
  border: 1px solid var(--border-light);
  border-radius: 12px;
  padding: 20px;
  transition: box-shadow 0.2s;
}

.card:hover {
  box-shadow: var(--shadow-md);
}

.card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 20px;
}

.card-head h3 {
  font-size: 15px;
  font-weight: 600;
  color: var(--text-primary);
}

/* ── Config layout ── */
.config-layout {
  display: grid;
  grid-template-columns: 200px 1fr;
  gap: 20px;
  min-height: 400px;
}

/* ── Section nav ── */
.section-nav {
  display: flex;
  flex-direction: column;
  gap: 4px;
  border-right: 1px solid var(--border-subtle);
  padding-right: 16px;
}

.section-btn {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border: none;
  background: transparent;
  border-radius: 8px;
  cursor: pointer;
  font-size: 13px;
  font-weight: 500;
  color: var(--text-secondary);
  transition: all 0.2s var(--ease-out);
  text-align: left;
}

.section-btn:hover {
  background: var(--bg-hover);
  color: var(--text-primary);
}

.section-btn.active {
  background: rgba(99,102,241,0.08);
  color: var(--info);
}

/* ── Config fields ── */
.config-fields {
  min-height: 300px;
}

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 300px;
  gap: 12px;
  color: var(--text-muted);
  font-size: 14px;
}

.field-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.field-row {
  display: grid;
  grid-template-columns: 200px 1fr;
  gap: 16px;
  align-items: center;
}

.field-label {
  font-size: 13px;
  font-weight: 500;
  color: var(--text-primary);
  font-family: var(--font-mono);
  word-break: break-all;
  display: flex;
  align-items: center;
  gap: 6px;
}

.field-row.edited {
  background: rgba(99,102,241,0.04);
  border-radius: 6px;
  padding: 2px 0;
}

.edited-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--indigo-500);
  flex-shrink: 0;
}
</style>
