<script setup lang="ts">
definePageMeta({
  layout: false,
})

const { $toast } = useNuxtApp()

interface ConfigMeta {
  key: string
  label: string
  description: string
  type: 'string' | 'boolean' | 'number'
  group: string
}

const configMeta: ConfigMeta[] = [
  { key: 'siteName', label: '站点名称', description: '网站标题，显示在浏览器标签和页面上', type: 'string', group: '基本设置' },
  { key: 'siteIcon', label: '站点图标', description: 'favicon 图标，支持上传或填写 URL。推荐 32×32 PNG / 16×16 ICO', type: 'string', group: '基本设置' },
  { key: 'allowRegister', label: '允许注册', description: '是否开放新用户注册功能', type: 'boolean', group: '基本设置' },

]

const form = reactive<Record<string, any>>(
  Object.fromEntries(configMeta.map(m => [m.key, m.type === 'boolean' ? false : m.type === 'number' ? 0 : '']))
)
const saving = reactive<Record<string, boolean>>({})

const { data, pending } = await useHttpFetch('/api/config/global')

// Map API response into reactive form
watchEffect(() => {
  if (data.value?.config) {
    for (const [key, value] of Object.entries(data.value.config)) {
      form[key] = value
    }
  }
})

async function handleSave(key: string) {
  saving[key] = true
  try {
    await $fetch('/api/config/global', {
      method: 'PUT',
      body: { key, value: form[key] },
    })
    $toast.success(`${configMeta.find(m => m.key === key)?.label || key} 已更新`)
    refreshNuxtData('global:config')
  } catch (e: any) {
    $toast.error(e?.data?.message || e?.message || '保存失败')
  } finally {
    saving[key] = false
  }
}

const uploading = ref(false)
const iconError = ref(false)

watch(() => form.siteIcon, () => { iconError.value = false })

function handleImgError(event: Event) {
  iconError.value = true
  ;(event.target as HTMLElement).style.display = 'none'
}

async function handleUpload() {
  if (import.meta.server) return
  // 动态创建 file input 绕过 v-for 中 ref 绑定问题
  const input = document.createElement('input')
  input.type = 'file'
  input.accept = 'image/png,image/jpeg,image/webp,image/x-icon,image/svg+xml'
  input.style.display = 'none'

  input.onchange = async () => {
    const file = input.files?.[0]
    if (!file) return

    uploading.value = true
    try {
      const fd = new FormData()
      fd.append('file', file)

      const res = await $fetch<{ code: number; data: { url: string }[] }>('/api/file/upload', {
        method: 'POST',
        body: fd,
      })
      if (res.code === 0 && res.data?.[0]?.url) {
        form.siteIcon = res.data[0].url
        await handleSave('siteIcon')
      } else {
        $toast.error('上传失败')
      }
    } catch (e: any) {
      $toast.error(e?.data?.message || e?.message || '上传失败')
    } finally {
      uploading.value = false
      input.remove()
    }
  }

  document.body.appendChild(input)
  input.click()
}

// ── 邮件配置 ──
const emailForm = reactive({
  host: '',
  port: 587,
  user: '',
  pass: '',
  from: '',
  secure: false,
})

const emailLoading = ref(false)
const emailTesting = ref(false)
const emailSending = ref(false)
const testTo = ref('')
const testResult = ref<{ success: boolean; message: string } | null>(null)

// 从全局配置数据初始化邮件表单
watchEffect(() => {
  if (data.value?.config) {
    const c = data.value.config
    if (c.smtpHost !== undefined) emailForm.host = c.smtpHost
    if (c.smtpPort !== undefined) emailForm.port = Number(c.smtpPort)
    if (c.smtpUser !== undefined) emailForm.user = c.smtpUser
    if (c.smtpFrom !== undefined) emailForm.from = c.smtpFrom
    if (c.smtpSecure !== undefined) emailForm.secure = Boolean(c.smtpSecure)
    // pass 服务端返回空字符串，保持局部状态不变
  }
})

async function handleEmailSave() {
  emailLoading.value = true
  try {
    await $fetch('/api/admin/email/config', {
      method: 'PUT',
      body: {
        host: emailForm.host,
        port: emailForm.port,
        user: emailForm.user,
        pass: emailForm.pass,
        from: emailForm.from,
        secure: emailForm.secure,
      },
    })
    $toast.success('邮件配置已保存')
    refreshNuxtData('global:config')
  } catch (e: any) {
    $toast.error(e?.data?.message || e?.message || '保存失败')
  } finally {
    emailLoading.value = false
  }
}

async function handleTestConnection() {
  emailTesting.value = true
  testResult.value = null
  try {
    const res = await $fetch<{ code: number; data: { success: boolean; message: string }; message?: string }>('/api/admin/email/test', { method: 'POST' })
    testResult.value = res.code === 0 ? res.data : { success: false, message: res.message || '测试失败' }
    if (testResult.value?.success) {
      $toast.success('SMTP 连接测试成功')
    } else {
      $toast.error(testResult.value?.message || '连接测试失败')
    }
  } catch (e: any) {
    const msg = e?.data?.message || e?.message || '测试请求失败'
    testResult.value = { success: false, message: msg }
    $toast.error(msg)
  } finally {
    emailTesting.value = false
  }
}

async function handleSendTest() {
  if (!testTo.value) {
    $toast.warning('请输入测试收件地址')
    return
  }
  emailSending.value = true
  try {
    const res = await $fetch<{ code: number; data: { success: boolean; message: string }; message?: string }>('/api/admin/email/send', {
      method: 'POST',
      body: { to: testTo.value },
    })
    if (res.code === 0 && res.data?.success) {
      $toast.success('测试邮件已发送')
    } else {
      $toast.error(res?.data?.message || res?.message || '发送失败')
    }
  } catch (e: any) {
    $toast.error(e?.data?.message || e?.message || '发送失败')
  } finally {
    emailSending.value = false
  }
}

const groups = computed(() => {
  const map = new Map<string, ConfigMeta[]>()
  for (const meta of configMeta) {
    if (!map.has(meta.group)) map.set(meta.group, [])
    map.get(meta.group)!.push(meta)
  }
  return Array.from(map.entries())
})
</script>

<template>
  <div class="config-page">
    <header class="page-header">
      <h1 class="page-title">全局配置</h1>
      <p class="page-subtitle">管理系统全局设置项</p>
    </header>

    <div v-if="pending && !data" class="loading-state">
      <div class="loading-spinner" />
      <p>加载中...</p>
    </div>

    <template v-else>
      <div v-for="[groupName, items] in groups" :key="groupName" class="config-card">
        <h2 class="section-title">{{ groupName }}</h2>

        <div class="config-list">
          <div v-for="meta in items" :key="meta.key" class="config-row">
            <div class="config-info">
              <label class="config-label">{{ meta.label }}</label>
              <p class="config-desc">{{ meta.description }}</p>
            </div>

            <div class="config-control">
              <!-- Boolean: toggle -->
              <div v-if="meta.type === 'boolean'" class="toggle-wrap">
                <label class="toggle">
                  <input
                    v-model="form[meta.key]"
                    type="checkbox"
                    class="toggle-input"
                    :disabled="saving[meta.key]"
                  />
                  <span class="toggle-slider" />
                </label>
                <span class="toggle-value">{{ form[meta.key] ? '开启' : '关闭' }}</span>
                <button
                  class="btn-save btn-save--sm"
                  :disabled="saving[meta.key]"
                  @click="handleSave(meta.key)"
                >
                  {{ saving[meta.key] ? '...' : '保存' }}
                </button>
              </div>

              <!-- String / Number: input -->
              <div v-else class="input-wrap">
                <!-- siteIcon: upload + URL input -->
                <template v-if="meta.key === 'siteIcon'">
                  <img
                    v-show="!!form[meta.key] && !iconError"
                    :src="form[meta.key]"
                    class="icon-preview"
                    alt=""
                    @error="handleImgError"
                  />
                  <input
                    v-model="form[meta.key]"
                    type="text"
                    class="form-input"
                    :class="{ 'form-input--with-preview': form[meta.key] }"
                    :disabled="saving[meta.key] || uploading"
                    placeholder="图标 URL 或上传图片"
                  />
                  <button
                    class="btn-upload"
                    :disabled="uploading"
                    @click="handleUpload"
                  >
                    {{ uploading ? '上传中...' : '上传' }}
                  </button>
                  <button
                    class="btn-save"
                    :disabled="saving[meta.key]"
                    @click="handleSave(meta.key)"
                  >
                    {{ saving[meta.key] ? '保存中...' : '保存' }}
                  </button>
                </template>

                <!-- Regular string/number input -->
                <template v-else>
                  <input
                    v-model="form[meta.key]"
                    :type="meta.type === 'number' ? 'number' : 'text'"
                    class="form-input"
                    :disabled="saving[meta.key]"
                    :placeholder="'输入' + meta.label"
                  />
                  <button
                    class="btn-save"
                    :disabled="saving[meta.key]"
                    @click="handleSave(meta.key)"
                  >
                    {{ saving[meta.key] ? '保存中...' : '保存' }}
                  </button>
                </template>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- ── 邮件配置（内嵌） ── -->
      <div class="config-card">
        <h2 class="section-title">SMTP 服务器设置</h2>

        <form class="email-form" @submit.prevent="handleEmailSave">
          <div class="form-row">
            <div class="form-group">
              <label class="form-label">SMTP 服务器地址</label>
              <input
                v-model="emailForm.host"
                type="text"
                class="form-input"
                placeholder="例如 smtp.example.com"
              />
            </div>

            <div class="form-group">
              <label class="form-label">端口</label>
              <input
                v-model.number="emailForm.port"
                type="number"
                class="form-input"
                placeholder="587"
                min="1"
                max="65535"
              />
            </div>
          </div>

          <div class="form-row">
            <div class="form-group">
              <label class="form-label">用户名</label>
              <input
                v-model="emailForm.user"
                type="text"
                class="form-input"
                placeholder="SMTP 用户名"
              />
            </div>

            <div class="form-group">
              <label class="form-label">密码</label>
              <input
                v-model="emailForm.pass"
                type="password"
                class="form-input"
                placeholder="SMTP 密码"
              />
            </div>
          </div>

          <div class="form-row">
            <div class="form-group">
              <label class="form-label">发件人地址</label>
              <input
                v-model="emailForm.from"
                type="email"
                class="form-input"
                placeholder="例如 noreply@example.com"
              />
            </div>

            <div class="form-group form-group-check">
              <label class="form-label">&nbsp;</label>
              <label class="form-check-label">
                <input v-model="emailForm.secure" type="checkbox" class="form-checkbox" />
                <span>使用 SSL/TLS 加密连接</span>
              </label>
            </div>
          </div>

          <div class="form-actions">
            <button type="submit" class="btn-primary" :disabled="emailLoading">
              {{ emailLoading ? '保存中...' : '保存配置' }}
            </button>
            <button type="button" class="btn-outline" :disabled="emailTesting" @click="handleTestConnection">
              {{ emailTesting ? '测试中...' : '测试连接' }}
            </button>
          </div>
        </form>
      </div>

      <div class="config-card">
        <h2 class="section-title">发送测试邮件</h2>
        <p class="section-desc">使用当前 SMTP 配置发送一封测试邮件，验证邮件发送功能是否正常。</p>

        <div class="test-send-row">
          <input
            v-model="testTo"
            type="email"
            class="form-input test-input"
            placeholder="输入收件人邮箱地址"
          />
          <button class="btn-primary" :disabled="emailSending" @click="handleSendTest">
            {{ emailSending ? '发送中...' : '发送测试邮件' }}
          </button>
        </div>
      </div>
    </template>
  </div>
</template>

<style scoped>
.config-page {
  padding: 40px;
  max-width: 800px;
}

.page-header {
  margin-bottom: 32px;
}

.page-title {
  font-family: var(--font-display);
  font-size: 32px;
  font-weight: 400;
  color: var(--color-ink);
  letter-spacing: -0.3px;
  margin: 0 0 8px 0;
}

.page-subtitle {
  font-size: 15px;
  color: var(--color-muted);
  margin: 0;
}

.config-card {
  background: var(--color-surface-card);
  border-radius: 12px;
  padding: 24px;
  margin-bottom: 20px;
}

.section-title {
  font-size: 12px;
  font-weight: 600;
  color: var(--color-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin: 0 0 16px 0;
}

.config-list {
  display: flex;
  flex-direction: column;
  gap: 0;
}

.config-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 0;
  gap: 24px;
}

.config-row + .config-row {
  border-top: 1px solid var(--color-hairline);
}

.config-info {
  flex: 1;
  min-width: 0;
}

.config-label {
  font-size: 14px;
  font-weight: 500;
  color: var(--color-body-strong);
  margin: 0 0 4px;
}

.config-desc {
  font-size: 13px;
  color: var(--color-muted);
  margin: 0;
}

.config-control {
  flex-shrink: 0;
}

/* Input */
.input-wrap {
  display: flex;
  align-items: center;
  gap: 8px;
  position: relative;
}

.form-input {
  width: 240px;
  padding: 10px 14px;
  font-size: 14px;
  color: var(--color-ink);
  background: var(--color-canvas);
  border: 1px solid var(--color-hairline);
  border-radius: 8px;
  transition: all 0.15s ease;
  box-sizing: border-box;
}

.form-input:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px rgba(204, 120, 92, 0.15);
}

.form-input:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.form-input--with-preview {
  padding-left: 42px;
}

.icon-preview {
  position: absolute;
  left: 10px;
  width: 20px;
  height: 20px;
  border-radius: 4px;
  object-fit: contain;
  flex-shrink: 0;
  pointer-events: none;
}

/* Toggle switch */
.toggle-wrap {
  display: flex;
  align-items: center;
  gap: 12px;
}

.toggle {
  position: relative;
  display: inline-block;
  width: 44px;
  height: 24px;
  cursor: pointer;
}

.toggle-input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}

.toggle-slider {
  position: absolute;
  inset: 0;
  background: var(--color-hairline);
  border-radius: 24px;
  transition: background 0.2s ease;
}

.toggle-slider::after {
  content: '';
  position: absolute;
  top: 3px;
  left: 3px;
  width: 18px;
  height: 18px;
  background: #fff;
  border-radius: 50%;
  transition: transform 0.2s ease;
}

.toggle-input:checked + .toggle-slider {
  background: var(--color-primary);
}

.toggle-input:checked + .toggle-slider::after {
  transform: translateX(20px);
}

.toggle-input:disabled + .toggle-slider {
  opacity: 0.5;
  cursor: not-allowed;
}

.toggle-value {
  font-size: 13px;
  color: var(--color-muted);
  min-width: 28px;
}

/* Buttons */
.btn-save {
  padding: 8px 16px;
  font-size: 13px;
  font-weight: 500;
  color: var(--color-on-primary);
  background: var(--color-primary);
  border: none;
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.15s ease;
  white-space: nowrap;
}

.btn-save:hover {
  background: var(--color-primary-active);
}

.btn-save:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.btn-save--sm {
  padding: 6px 12px;
  font-size: 12px;
}

.btn-upload {
  padding: 8px 16px;
  font-size: 13px;
  font-weight: 500;
  color: var(--color-ink);
  background: var(--color-surface-soft);
  border: 1px solid var(--color-hairline);
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.15s ease;
  white-space: nowrap;
}

.btn-upload:hover {
  background: var(--color-hairline);
}

.btn-upload:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Loading */
.loading-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 200px;
  color: var(--color-muted);
}

.loading-spinner {
  width: 28px;
  height: 28px;
  border: 3px solid var(--color-hairline);
  border-top-color: var(--color-primary);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
  margin-bottom: 12px;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

/* ── Email Section ── */
.email-form {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}

.form-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.form-label {
  font-size: 14px;
  font-weight: 500;
  color: var(--color-body-strong);
}

.form-group-check {
  justify-content: flex-end;
}

.form-check-label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  color: var(--color-ink);
  cursor: pointer;
}

.form-checkbox {
  width: 18px;
  height: 18px;
  accent-color: var(--color-primary);
  cursor: pointer;
}

.form-actions {
  display: flex;
  gap: 12px;
  padding-top: 8px;
}

.btn-primary {
  padding: 12px 24px;
  font-size: 14px;
  font-weight: 500;
  color: var(--color-on-primary);
  background: var(--color-primary);
  border: none;
  border-radius: 8px;
  cursor: pointer;
  transition: background 0.15s ease;
}

.btn-primary:hover {
  background: var(--color-primary-active);
}

.btn-primary:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.btn-outline {
  padding: 12px 24px;
  font-size: 14px;
  font-weight: 500;
  color: var(--color-ink);
  background: transparent;
  border: 1px solid var(--color-hairline);
  border-radius: 8px;
  cursor: pointer;
  transition: all 0.15s ease;
}

.btn-outline:hover {
  background: var(--color-surface-soft);
}

.btn-outline:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.section-desc {
  font-size: 14px;
  color: var(--color-muted);
  margin: 0 0 16px 0;
}

.test-send-row {
  display: flex;
  gap: 12px;
  align-items: center;
}

.test-input {
  flex: 1;
}

@media (max-width: 768px) {
  .config-page {
    padding: 24px;
  }

  .config-row {
    flex-direction: column;
    align-items: flex-start;
    gap: 12px;
  }

  .input-wrap {
    width: 100%;
  }

  .form-input {
    width: 100%;
  }

  .form-row {
    grid-template-columns: 1fr;
  }

  .test-send-row {
    flex-direction: column;
    align-items: stretch;
  }
}
</style>
