<script setup>
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'

import { fetchSocialLoginConfig, fetchSystemConfig, testSocialLoginConfig, updateSocialLoginConfig, updateSystemConfig } from '../api/system'
import { fetchKdocsQr, fetchKdocsStatus, clearKdocsLogin } from '../api/kdocs'
import { fetchProxyConfig, testProxy, updateProxyConfig } from '../api/proxy'
import { getCachedKdocsStatus, preloadKdocsStatus, updateCachedKdocsStatus } from '../utils/kdocsStatusCache'

const loading = ref(false)

const maxConcurrentGlobal = ref(2)
const maxConcurrentPerAccount = ref(1)
const maxScreenshotConcurrent = ref(3)
const dbSlowQueryMs = ref(120)

const proxyEnabled = ref(false)
const proxyApiUrl = ref('')
const proxyExpireMinutes = ref(3)

const autoApproveEnabled = ref(false)
const autoApproveHourlyLimit = ref(10)
const autoApproveVipDays = ref(7)

const socialLoginEnabled = ref(false)
const socialLoginEndpoint = ref('https://www.spacezs.cn/connect.php')
const socialLoginAppid = ref('')
const socialLoginAppkey = ref('')
const socialLoginAppkeyMasked = ref('')
const socialLoginAppkeyConfigured = ref(false)
const socialLoginProviders = ref(['wx'])
const socialLoginSaving = ref(false)
const socialLoginTesting = ref(false)
const socialProviderOptions = [
  { label: 'QQ', value: 'qq' },
  { label: '微信', value: 'wx' },
  { label: '支付宝', value: 'alipay' },
]

const kdocsEnabled = ref(false)
const kdocsDocUrl = ref('')
const kdocsDefaultUnit = ref('')
const kdocsSheetName = ref('')
const kdocsSheetIndex = ref(0)
const kdocsUnitColumn = ref('A')
const kdocsImageColumn = ref('D')
const kdocsRowStart = ref(0)
const kdocsRowEnd = ref(0)
const kdocsAdminNotifyEnabled = ref(false)
const kdocsAdminNotifyEmail = ref('')

const initialKdocsStatus = getCachedKdocsStatus({ maxAgeMs: 10 * 60 * 1000 })
const kdocsStatus = ref(initialKdocsStatus || {})
const kdocsQrOpen = ref(false)
const kdocsQrImage = ref('')
const kdocsPolling = ref(false)
const kdocsStatusLoading = ref(false)
const kdocsQrLoading = ref(false)
const kdocsClearLoading = ref(false)
const kdocsSilentRefreshing = ref(!initialKdocsStatus)
const kdocsActionHint = ref('')
let kdocsPollingTimer = null

const kdocsActionBusy = computed(
  () => kdocsStatusLoading.value || kdocsQrLoading.value || kdocsClearLoading.value,
)

const kdocsDetecting = computed(
  () => kdocsSilentRefreshing.value || kdocsStatusLoading.value || kdocsPolling.value,
)

const kdocsStatusText = computed(() => {
  if (kdocsDetecting.value) return '检测中'
  const status = kdocsStatus.value || {}
  if (status?.logged_in === true || status?.last_login_ok === true) return '已登录'
  if (status?.logged_in === false || status?.last_login_ok === false || status?.login_required === true) return '未登录'
  if (status?.last_error) return '异常'
  return '未知'
})

const kdocsStatusClass = computed(() => {
  if (kdocsDetecting.value) return 'is-checking'
  if (kdocsStatusText.value === '已登录') return 'is-online'
  if (kdocsStatusText.value === '未登录') return 'is-offline'
  if (kdocsStatusText.value === '异常') return 'is-error'
  return 'is-unknown'
})

function setKdocsHint(message) {
  if (!message) {
    kdocsActionHint.value = ''
    return
  }
  const time = new Date().toLocaleTimeString('zh-CN', { hour12: false })
  kdocsActionHint.value = `${message} (${time})`
}

async function loadAll() {
  loading.value = true
  try {
    const [system, proxy, social] = await Promise.all([
      fetchSystemConfig(),
      fetchProxyConfig(),
      fetchSocialLoginConfig(),
    ])

    maxConcurrentGlobal.value = system.max_concurrent_global ?? 2
    maxConcurrentPerAccount.value = system.max_concurrent_per_account ?? 1
    maxScreenshotConcurrent.value = system.max_screenshot_concurrent ?? 3
    dbSlowQueryMs.value = system.db_slow_query_ms ?? 120

    autoApproveEnabled.value = (system.auto_approve_enabled ?? 0) === 1
    autoApproveHourlyLimit.value = system.auto_approve_hourly_limit ?? 10
    autoApproveVipDays.value = system.auto_approve_vip_days ?? 7

    proxyEnabled.value = (proxy.proxy_enabled ?? 0) === 1
    proxyApiUrl.value = proxy.proxy_api_url || ''
    proxyExpireMinutes.value = proxy.proxy_expire_minutes ?? 3

    kdocsEnabled.value = (system.kdocs_enabled ?? 0) === 1
    kdocsDocUrl.value = system.kdocs_doc_url || ''
    kdocsDefaultUnit.value = system.kdocs_default_unit || ''
    kdocsSheetName.value = system.kdocs_sheet_name || ''
    kdocsSheetIndex.value = system.kdocs_sheet_index ?? 0
    kdocsUnitColumn.value = (system.kdocs_unit_column || 'A').toUpperCase()
    kdocsImageColumn.value = (system.kdocs_image_column || 'D').toUpperCase()
    kdocsRowStart.value = system.kdocs_row_start ?? 0
    kdocsRowEnd.value = system.kdocs_row_end ?? 0
    kdocsAdminNotifyEnabled.value = (system.kdocs_admin_notify_enabled ?? 0) === 1
    kdocsAdminNotifyEmail.value = system.kdocs_admin_notify_email || ''

    socialLoginEnabled.value = (social.social_login_enabled ?? 0) === 1
    socialLoginEndpoint.value = social.social_login_endpoint || 'https://www.spacezs.cn/connect.php'
    socialLoginAppid.value = social.social_login_appid || ''
    socialLoginAppkey.value = ''
    socialLoginAppkeyMasked.value = social.social_login_appkey_masked || ''
    socialLoginAppkeyConfigured.value = Boolean(social.social_login_appkey_configured)
    socialLoginProviders.value = Array.isArray(social.social_login_providers) && social.social_login_providers.length
      ? social.social_login_providers
      : ['wx']
  } catch {
    // handled by interceptor
  } finally {
    loading.value = false
  }

  const cachedStatus = getCachedKdocsStatus({ maxAgeMs: 10 * 60 * 1000 })
  if (cachedStatus) {
    kdocsStatus.value = cachedStatus
    kdocsSilentRefreshing.value = false
  }

  // 静默刷新金山登录状态，确保状态持续更新且不阻塞首屏。
  void refreshKdocsStatusSilently()
}

async function refreshKdocsStatusSilently() {
  if (kdocsSilentRefreshing.value || kdocsStatusLoading.value) return
  kdocsSilentRefreshing.value = true
  try {
    const status = await preloadKdocsStatus({
      force: false,
      maxAgeMs: 60_000,
      silent: true,
      live: 0,
    })
    kdocsStatus.value = status || {}
  } catch {
    // silent mode
  } finally {
    kdocsSilentRefreshing.value = false
  }
}

async function saveConcurrency() {
  const payload = {
    max_concurrent_global: Number(maxConcurrentGlobal.value),
    max_concurrent_per_account: Number(maxConcurrentPerAccount.value),
    max_screenshot_concurrent: Number(maxScreenshotConcurrent.value),
    db_slow_query_ms: Number(dbSlowQueryMs.value),
  }

  try {
    await ElMessageBox.confirm(
      `确定更新并发配置吗？\n\n全局并发数: ${payload.max_concurrent_global}\n单账号并发数: ${payload.max_concurrent_per_account}\n截图并发数: ${payload.max_screenshot_concurrent}\n慢 SQL 阈值: ${payload.db_slow_query_ms}ms`,
      '保存并发配置',
      { confirmButtonText: '保存', cancelButtonText: '取消', type: 'warning' },
    )
  } catch {
    return
  }

  try {
    const res = await updateSystemConfig(payload)
    ElMessage.success(res?.message || '并发配置已更新')
  } catch {
    // handled by interceptor
  }
}

async function saveProxy() {
  if (proxyEnabled.value && !proxyApiUrl.value.trim()) {
    ElMessage.error('启用代理时，API地址不能为空')
    return
  }

  const payload = {
    proxy_enabled: proxyEnabled.value ? 1 : 0,
    proxy_api_url: proxyApiUrl.value.trim(),
    proxy_expire_minutes: Number(proxyExpireMinutes.value) || 3,
  }

  try {
    const res = await updateProxyConfig(payload)
    ElMessage.success(res?.message || '代理配置已更新')
  } catch {
    // handled by interceptor
  }
}

async function onTestProxy() {
  if (!proxyApiUrl.value.trim()) {
    ElMessage.error('请先输入代理API地址')
    return
  }

  try {
    const res = await testProxy({ api_url: proxyApiUrl.value.trim() })
    await ElMessageBox.alert(res?.message || '测试完成', '代理测试', { confirmButtonText: '知道了' })
  } catch {
    // handled by interceptor
  }
}

async function saveAutoApprove() {
  const hourly = Number(autoApproveHourlyLimit.value)
  const vipDays = Number(autoApproveVipDays.value)

  if (!Number.isFinite(hourly) || hourly < 1) {
    ElMessage.error('每小时注册限制必须大于0')
    return
  }
  if (!Number.isFinite(vipDays) || vipDays < 0) {
    ElMessage.error('VIP天数不能为负数')
    return
  }

  const payload = {
    auto_approve_enabled: autoApproveEnabled.value ? 1 : 0,
    auto_approve_hourly_limit: hourly,
    auto_approve_vip_days: vipDays,
  }

  try {
    const res = await updateSystemConfig(payload)
    ElMessage.success(res?.message || '注册设置已保存')
  } catch {
    // handled by interceptor
  }
}

function socialLoginPayload() {
  return {
    social_login_enabled: socialLoginEnabled.value ? 1 : 0,
    social_login_endpoint: socialLoginEndpoint.value.trim() || 'https://www.spacezs.cn/connect.php',
    social_login_appid: socialLoginAppid.value.trim(),
    social_login_appkey: socialLoginAppkey.value.trim(),
    social_login_providers: socialLoginProviders.value,
  }
}

function validateSocialLoginForm() {
  if (!socialLoginEnabled.value) return true
  if (!socialLoginProviders.value.length) {
    ElMessage.error('请选择至少一种登录方式')
    return false
  }
  if (!socialLoginEndpoint.value.trim()) {
    ElMessage.error('请输入聚合接口地址')
    return false
  }
  if (!socialLoginAppid.value.trim()) {
    ElMessage.error('请输入 APPID')
    return false
  }
  if (!socialLoginAppkey.value.trim() && !socialLoginAppkeyConfigured.value) {
    ElMessage.error('请输入 APPKEY')
    return false
  }
  return true
}

async function saveSocialLogin() {
  if (!validateSocialLoginForm()) return
  socialLoginSaving.value = true
  try {
    const res = await updateSocialLoginConfig(socialLoginPayload())
    const cfg = res?.config || {}
    socialLoginAppkey.value = ''
    socialLoginAppkeyMasked.value = cfg.social_login_appkey_masked || socialLoginAppkeyMasked.value
    socialLoginAppkeyConfigured.value = Boolean(cfg.social_login_appkey_configured)
    ElMessage.success(res?.message || '聚合登录配置已保存')
  } catch {
    // handled by interceptor
  } finally {
    socialLoginSaving.value = false
  }
}

async function onTestSocialLogin() {
  if (!validateSocialLoginForm()) return
  socialLoginTesting.value = true
  try {
    const url = new URL(window.location.href)
    url.pathname = '/login'
    url.search = ''
    url.hash = ''
    const provider = socialLoginProviders.value[0] || 'wx'
    const res = await testSocialLoginConfig({
      ...socialLoginPayload(),
      provider,
      redirect_uri: url.toString(),
    })
    await ElMessageBox.alert(res?.success ? '连接正常' : '测试完成', '聚合登录测试', {
      confirmButtonText: '知道了',
    })
  } catch {
    // handled by interceptor
  } finally {
    socialLoginTesting.value = false
  }
}

async function saveKdocsConfig() {
  const payload = {
    kdocs_enabled: kdocsEnabled.value ? 1 : 0,
    kdocs_doc_url: kdocsDocUrl.value.trim(),
    kdocs_default_unit: kdocsDefaultUnit.value.trim(),
    kdocs_sheet_name: kdocsSheetName.value.trim(),
    kdocs_sheet_index: Number(kdocsSheetIndex.value) || 0,
    kdocs_unit_column: kdocsUnitColumn.value.trim().toUpperCase(),
    kdocs_image_column: kdocsImageColumn.value.trim().toUpperCase(),
    kdocs_row_start: Number(kdocsRowStart.value) || 0,
    kdocs_row_end: Number(kdocsRowEnd.value) || 0,
    kdocs_admin_notify_enabled: kdocsAdminNotifyEnabled.value ? 1 : 0,
    kdocs_admin_notify_email: kdocsAdminNotifyEmail.value.trim(),
  }

  try {
    const res = await updateSystemConfig(payload)
    ElMessage.success(res?.message || '表格配置已更新')
  } catch {
    // handled by interceptor
  }
}

async function refreshKdocsStatus() {
  if (kdocsStatusLoading.value) return
  kdocsStatusLoading.value = true
  setKdocsHint('正在刷新状态')
  try {
    const status = await fetchKdocsStatus({ live: 1 })
    kdocsStatus.value = status || {}
    updateCachedKdocsStatus(kdocsStatus.value)
    setKdocsHint('状态已刷新')
  } catch {
    setKdocsHint('刷新失败，请稍后重试')
  } finally {
    kdocsStatusLoading.value = false
  }
}

async function pollKdocsStatus() {
  try {
    const status = await fetchKdocsStatus({ live: 1 })
    kdocsStatus.value = status || {}
    updateCachedKdocsStatus(kdocsStatus.value)
    const loggedIn = status?.logged_in === true || status?.last_login_ok === true
    if (loggedIn) {
      ElMessage.success('扫码成功，已登录')
      setKdocsHint('扫码成功，已登录')
      kdocsQrOpen.value = false
      stopKdocsPolling()
    }
  } catch {
    // handled by interceptor
  }
}

function startKdocsPolling() {
  stopKdocsPolling()
  kdocsPolling.value = true
  setKdocsHint('扫码检测中')
  pollKdocsStatus()
  kdocsPollingTimer = setInterval(pollKdocsStatus, 2000)
}

function stopKdocsPolling() {
  if (kdocsPollingTimer) {
    clearInterval(kdocsPollingTimer)
    kdocsPollingTimer = null
  }
  kdocsPolling.value = false
}

async function onFetchKdocsQr() {
  if (kdocsQrLoading.value) return
  kdocsQrLoading.value = true
  setKdocsHint('正在获取二维码')
  try {
    kdocsQrImage.value = ''
    const res = await fetchKdocsQr()
    kdocsQrImage.value = res?.qr_image || ''
    if (!kdocsQrImage.value) {
      if (res?.logged_in) {
        ElMessage.success('当前已登录，无需扫码')
        setKdocsHint('当前已登录，无需扫码')
        await refreshKdocsStatus()
        return
      }
      ElMessage.warning('未获取到二维码')
      setKdocsHint('未获取到二维码')
      return
    }
    setKdocsHint('二维码已获取')
    kdocsQrOpen.value = true
  } catch {
    setKdocsHint('获取二维码失败')
  } finally {
    kdocsQrLoading.value = false
  }
}

async function onClearKdocsLogin() {
  if (kdocsClearLoading.value) return
  kdocsClearLoading.value = true
  setKdocsHint('正在清除登录态')
  try {
    await clearKdocsLogin()
    kdocsQrOpen.value = false
    kdocsQrImage.value = ''
    kdocsStatus.value = updateCachedKdocsStatus({
      ...(kdocsStatus.value || {}),
      logged_in: false,
      last_login_ok: false,
      login_required: true,
    })
    ElMessage.success('登录态已清除')
    setKdocsHint('登录态已清除')
    await refreshKdocsStatus()
  } catch {
    setKdocsHint('清除登录态失败')
  } finally {
    kdocsClearLoading.value = false
  }
}

watch(kdocsQrOpen, (open) => {
  if (open) {
    startKdocsPolling()
  } else {
    stopKdocsPolling()
  }
})

onBeforeUnmount(() => {
  stopKdocsPolling()
})

onMounted(loadAll)
</script>

<template>
  <div class="page-stack" v-loading="loading">
    <div class="app-page-title">
      <h2>系统配置</h2>
    </div>

    <div class="config-grid">
      <el-card shadow="never" :body-style="{ padding: '16px' }" class="card section-card">
        <h3 class="section-title">并发配置</h3>
        <div class="section-sub app-muted">控制任务与截图的并发资源上限</div>

        <el-form label-width="122px">
          <el-form-item label="全局最大并发数">
            <el-input-number v-model="maxConcurrentGlobal" :min="1" :max="200" />
            <div class="help">同时最多运行账号数（浏览任务 API 执行，资源占用较低）。</div>
          </el-form-item>

          <el-form-item label="单账号最大并发数">
            <el-input-number v-model="maxConcurrentPerAccount" :min="1" :max="50" />
            <div class="help">建议保持为 1，避免同账号任务抢占。</div>
          </el-form-item>

          <el-form-item label="截图最大并发数">
            <el-input-number v-model="maxScreenshotConcurrent" :min="1" :max="50" />
            <div class="help">截图资源占用较低，可按机器性能逐步提高。</div>
          </el-form-item>

          <el-form-item label="慢 SQL 阈值(ms)">
            <el-input-number v-model="dbSlowQueryMs" :min="0" :max="60000" />
            <div class="help">低于该阈值不会计入慢 SQL（0 表示关闭慢 SQL 采样）。</div>
          </el-form-item>
        </el-form>

        <div class="row-actions">
          <el-button type="primary" @click="saveConcurrency">保存并发配置</el-button>
        </div>
      </el-card>

      <el-card shadow="never" :body-style="{ padding: '16px' }" class="card section-card">
        <h3 class="section-title">代理设置</h3>
        <div class="section-sub app-muted">用于任务出网代理与连接有效期管理</div>

        <el-form label-width="122px">
          <el-form-item label="启用 IP 代理">
            <el-switch v-model="proxyEnabled" />
            <div class="help">开启后，浏览任务通过代理访问，失败自动重试。</div>
          </el-form-item>

          <el-form-item label="代理 API 地址">
            <el-input v-model="proxyApiUrl" placeholder="http://api.xxx/Tools/IP.ashx?..." />
            <div class="help">API 应返回 `IP:PORT`（例：123.45.67.89:8888）。</div>
          </el-form-item>

          <el-form-item label="有效期(分钟)">
            <el-input-number v-model="proxyExpireMinutes" :min="1" :max="60" />
          </el-form-item>
        </el-form>

        <div class="row-actions">
          <el-button type="primary" @click="saveProxy">保存代理配置</el-button>
          <el-button @click="onTestProxy">测试代理</el-button>
        </div>
      </el-card>

      <el-card shadow="never" :body-style="{ padding: '16px' }" class="card section-card">
        <h3 class="section-title">注册设置</h3>
        <div class="section-sub app-muted">控制注册节流与新用户赠送 VIP</div>

        <el-form label-width="122px">
          <el-form-item label="注册赠送 VIP">
            <el-switch v-model="autoApproveEnabled" />
            <div class="help">开启后，新用户注册成功自动赠送下方设定的 VIP 天数。</div>
          </el-form-item>

          <el-form-item label="每小时注册限制">
            <el-input-number v-model="autoApproveHourlyLimit" :min="1" :max="10000" />
          </el-form-item>

          <el-form-item label="赠送 VIP 天数">
            <el-input-number v-model="autoApproveVipDays" :min="0" :max="999999" />
          </el-form-item>
        </el-form>

        <div class="row-actions">
          <el-button type="primary" @click="saveAutoApprove">保存注册设置</el-button>
        </div>
      </el-card>

      <el-card shadow="never" :body-style="{ padding: '16px' }" class="card section-card social-card">
        <h3 class="section-title">聚合登录</h3>
        <div class="section-sub app-muted">QQ、微信、支付宝快捷登录</div>

        <el-form label-width="122px">
          <el-form-item label="启用">
            <el-switch v-model="socialLoginEnabled" />
          </el-form-item>

          <el-form-item label="登录方式">
            <el-checkbox-group v-model="socialLoginProviders">
              <el-checkbox v-for="item in socialProviderOptions" :key="item.value" :label="item.value">
                {{ item.label }}
              </el-checkbox>
            </el-checkbox-group>
          </el-form-item>

          <el-form-item label="接口地址">
            <el-input v-model="socialLoginEndpoint" placeholder="https://www.spacezs.cn/connect.php" />
          </el-form-item>

          <el-form-item label="APPID">
            <el-input v-model="socialLoginAppid" placeholder="Space APPID" />
          </el-form-item>

          <el-form-item label="APPKEY">
            <el-input v-model="socialLoginAppkey" type="password" show-password placeholder="留空则保持当前密钥" />
            <div v-if="socialLoginAppkeyConfigured" class="help">当前：{{ socialLoginAppkeyMasked }}</div>
          </el-form-item>
        </el-form>

        <div class="row-actions">
          <el-button type="primary" :loading="socialLoginSaving" @click="saveSocialLogin">保存聚合登录</el-button>
          <el-button :loading="socialLoginTesting" @click="onTestSocialLogin">测试连接</el-button>
        </div>
      </el-card>
    </div>

    <el-card shadow="never" :body-style="{ padding: '16px' }" class="card kdocs-card">
      <div class="section-head">
        <h3 class="section-title">金山文档上传</h3>
        <div class="status-inline app-muted">
          <span>登录状态：</span>
          <span class="status-chip" :class="kdocsStatusClass">
            {{ kdocsStatusText }}
            <span v-if="kdocsDetecting" class="status-dots" aria-hidden="true">
              <i></i><i></i><i></i>
            </span>
          </span>
          <span>· 待上传 {{ kdocsStatus.queue_size || 0 }}</span>
        </div>
      </div>

      <el-form label-width="118px" class="kdocs-form">
        <el-form-item label="启用上传">
          <el-switch v-model="kdocsEnabled" />
          <div class="help">表格结构变化时可先关闭，避免错误上传。</div>
        </el-form-item>

        <el-form-item label="文档链接">
          <el-input v-model="kdocsDocUrl" placeholder="https://kdocs.cn/..." />
        </el-form-item>

        <el-form-item label="默认县区">
          <el-input v-model="kdocsDefaultUnit" placeholder="如：道县（用户可覆盖）" />
        </el-form-item>

        <el-form-item label="Sheet 名称">
          <el-input v-model="kdocsSheetName" placeholder="留空使用第一个 Sheet" />
        </el-form-item>

        <el-form-item label="Sheet 序号">
          <el-input-number v-model="kdocsSheetIndex" :min="0" :max="50" />
          <div class="help">0 表示第一个 Sheet。</div>
        </el-form-item>

        <el-form-item label="列配置">
          <div class="kdocs-inline">
            <el-input v-model="kdocsUnitColumn" placeholder="县区列，如 A" />
            <el-input v-model="kdocsImageColumn" placeholder="图片列，如 D" />
          </div>
        </el-form-item>

        <el-form-item label="有效行范围">
          <div class="kdocs-range">
            <el-input-number v-model="kdocsRowStart" :min="0" :max="10000" placeholder="起始行" style="width: 140px" />
            <span class="app-muted">至</span>
            <el-input-number v-model="kdocsRowEnd" :min="0" :max="10000" placeholder="结束行" style="width: 140px" />
          </div>
          <div class="help">用于限制上传区间（如 50-100），0 表示不限制。</div>
        </el-form-item>

        <el-form-item label="管理员通知">
          <el-switch v-model="kdocsAdminNotifyEnabled" />
        </el-form-item>

        <el-form-item label="通知邮箱">
          <el-input v-model="kdocsAdminNotifyEmail" placeholder="admin@example.com" />
        </el-form-item>
      </el-form>

      <div class="row-actions">
        <el-button type="primary" @click="saveKdocsConfig">保存表格配置</el-button>
        <el-button
          type="success"
          plain
          :loading="kdocsQrLoading"
          :disabled="kdocsActionBusy && !kdocsQrLoading"
          @click="onFetchKdocsQr"
        >
          获取二维码
        </el-button>
        <el-button
          type="danger"
          plain
          :loading="kdocsClearLoading"
          :disabled="kdocsActionBusy && !kdocsClearLoading"
          @click="onClearKdocsLogin"
        >
          清除登录
        </el-button>
      </div>

      <div v-if="kdocsStatus.last_error" class="help">最近错误：{{ kdocsStatus.last_error }}</div>
      <div v-if="kdocsActionHint" class="help">操作提示：{{ kdocsActionHint }}</div>
    </el-card>

    <el-dialog v-model="kdocsQrOpen" title="扫码登录" width="min(420px, 92vw)">
      <div class="kdocs-qr">
        <img v-if="kdocsQrImage" :src="`data:image/png;base64,${kdocsQrImage}`" alt="KDocs QR" />
        <div class="help">请使用管理员微信扫码登录。</div>
      </div>
    </el-dialog>
  </div>
</template>

<style scoped>
.page-stack {
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-width: 0;
}

.config-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px;
}

.card {
  border-radius: var(--app-radius);
  border: 1px solid var(--app-border);
  background: var(--app-card-bg);
  box-shadow: var(--app-shadow-soft);
}

.section-card {
  min-width: 0;
}

.section-title {
  margin: 0;
  font-size: 15px;
  font-weight: 800;
  letter-spacing: 0.2px;
}

.section-sub {
  margin-top: 6px;
  margin-bottom: 10px;
  font-size: 12px;
}

.section-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}

.status-inline {
  font-size: 12px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.status-chip {
  display: inline-flex;
  align-items: center;
  min-height: 22px;
  padding: 0 8px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  border: 1px solid transparent;
}

.status-chip.is-checking {
  color: #1d4ed8;
  background: #dbeafe;
  border-color: #93c5fd;
}

.status-chip.is-online {
  color: #065f46;
  background: #d1fae5;
  border-color: #6ee7b7;
}

.status-chip.is-offline {
  color: #92400e;
  background: #fef3c7;
  border-color: #fcd34d;
}

.status-chip.is-error {
  color: #991b1b;
  background: #fee2e2;
  border-color: #fca5a5;
}

.status-chip.is-unknown {
  color: #374151;
  background: #f3f4f6;
  border-color: #d1d5db;
}

.status-dots {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  margin-left: 3px;
}

.status-dots i {
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.25;
  animation: dotPulse 1.2s infinite ease-in-out;
}

.status-dots i:nth-child(2) {
  animation-delay: 0.2s;
}

.status-dots i:nth-child(3) {
  animation-delay: 0.4s;
}

@keyframes dotPulse {
  0%,
  80%,
  100% {
    opacity: 0.25;
    transform: translateY(0);
  }
  40% {
    opacity: 1;
    transform: translateY(-1px);
  }
}

.kdocs-form {
  margin-top: 6px;
}

.kdocs-inline {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  width: 100%;
}

.kdocs-range {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.kdocs-qr {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}

.kdocs-qr img {
  width: 260px;
  max-width: 100%;
  border: 1px solid var(--app-border);
  border-radius: 8px;
  padding: 8px;
  background: #fff;
}

.help {
  margin-top: 6px;
  font-size: 12px;
  color: var(--app-muted);
}

.row-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

@media (max-width: 1200px) {
  .config-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1201px) {
  .social-card {
    grid-column: span 3;
  }
}

@media (max-width: 768px) {
  .config-grid {
    grid-template-columns: 1fr;
  }

  .kdocs-inline {
    grid-template-columns: 1fr;
  }

  .kdocs-range {
    align-items: stretch;
  }
}
</style>
