<script setup>
import { computed, onMounted, reactive, ref } from 'vue'
import { message, Modal } from 'ant-design-vue'
import { storeToRefs } from 'pinia'
import {
  RobotOutlined,
  FileTextOutlined,
  FilterOutlined,
  ReloadOutlined,
  SaveOutlined,
  UndoOutlined,
  LockOutlined
} from '@ant-design/icons-vue'
import {
  get as getSettings,
  update as updateSettings,
  schema as getSettingsSchema,
  reset as resetSettings
} from '@/api/settings'
import { useAuthStore } from '@/stores/useAuthStore'

const authStore = useAuthStore()
const { isAdmin } = storeToRefs(authStore)

const activeTab = ref('models')
const isLoading = ref(false)
const isSaving = ref(false)
const isResetting = ref(false)
const schemaData = ref(null)

const DEFAULT_MODEL_CONFIG = {
  provider: 'ollama',
  base_url: '',
  api_key: '',
  model: '',
  timeout: 120,
  temperature: 0.3
}

const form = reactive({
  models: {
    summarize: { ...DEFAULT_MODEL_CONFIG },
    query: { ...DEFAULT_MODEL_CONFIG },
    classify: { ...DEFAULT_MODEL_CONFIG }
  },
  parsers: {
    ocr: { plugin: '', params: {} },
    pdf: { plugin: '', params: {} },
    docx: { plugin: '', params: {} }
  },
  dedup: {
    strategy: 'sha256',
    simhash_threshold: 3,
    ttl_seconds: 86400
  }
})

const modelKeys = ['summarize', 'query', 'classify']
const modelMeta = {
  summarize: {
    label: '总结模型',
    key: 'summarize',
    desc: '用于文档三级总结',
    icon: RobotOutlined,
    color: '#1677ff'
  },
  query: {
    label: '查询模型',
    key: 'query',
    desc: '用于 query 解析与重写',
    icon: FilterOutlined,
    color: '#722ed1'
  },
  classify: {
    label: '分类模型',
    key: 'classify',
    desc: '用于文档分类判定',
    icon: FileTextOutlined,
    color: '#13c2c2'
  }
}

const llmProviderOptions = computed(() => {
  return (schemaData.value?.llm_providers || ['ollama', 'openai_compatible']).map(
    (p) => ({ label: p, value: p })
  )
})

const ocrPluginOptions = computed(() =>
  (schemaData.value?.ocr_plugins || []).map((p) => ({ label: p, value: p }))
)
const pdfPluginOptions = computed(() =>
  (schemaData.value?.pdf_plugins || []).map((p) => ({ label: p, value: p }))
)
const docxPluginOptions = computed(() =>
  (schemaData.value?.docx_plugins || []).map((p) => ({ label: p, value: p }))
)
const dedupStrategyOptions = computed(() =>
  (schemaData.value?.dedup_strategies || ['none', 'sha256', 'simhash']).map((s) => ({
    label: s,
    value: s
  }))
)

const isSimhash = computed(() => form.dedup.strategy === 'simhash')

function applySettingsToForm(cfg) {
  if (!cfg || typeof cfg !== 'object') return
  if (cfg.models && typeof cfg.models === 'object') {
    for (const key of modelKeys) {
      const src = cfg.models[key] || {}
      form.models[key] = {
        provider: src.provider ?? DEFAULT_MODEL_CONFIG.provider,
        base_url: src.base_url ?? '',
        api_key: src.api_key ?? '',
        model: src.model ?? '',
        timeout: src.timeout ?? 120,
        temperature: src.temperature ?? 0.3
      }
    }
  }
  if (cfg.parsers && typeof cfg.parsers === 'object') {
    const ocr = cfg.parsers.ocr || {}
    const pdf = cfg.parsers.pdf || {}
    const docx = cfg.parsers.docx || {}
    form.parsers.ocr = { plugin: ocr.plugin ?? '', params: ocr.params || {} }
    form.parsers.pdf = { plugin: pdf.plugin ?? '', params: pdf.params || {} }
    form.parsers.docx = { plugin: docx.plugin ?? '', params: docx.params || {} }
  }
  if (cfg.dedup && typeof cfg.dedup === 'object') {
    form.dedup.strategy = cfg.dedup.strategy ?? 'sha256'
    form.dedup.simhash_threshold = cfg.dedup.simhash_threshold ?? 3
    form.dedup.ttl_seconds = cfg.dedup.ttl_seconds ?? 86400
  }
}

function buildPayload() {
  return {
    models: {
      summarize: { ...form.models.summarize },
      query: { ...form.models.query },
      classify: { ...form.models.classify }
    },
    parsers: {
      ocr: { plugin: form.parsers.ocr.plugin, params: { ...form.parsers.ocr.params } },
      pdf: { plugin: form.parsers.pdf.plugin, params: { ...form.parsers.pdf.params } },
      docx: { plugin: form.parsers.docx.plugin, params: { ...form.parsers.docx.params } }
    },
    dedup: {
      strategy: form.dedup.strategy,
      simhash_threshold: form.dedup.simhash_threshold,
      ttl_seconds: form.dedup.ttl_seconds
    }
  }
}

async function loadAll() {
  isLoading.value = true
  try {
    const [cfg, schema] = await Promise.all([getSettings(), getSettingsSchema()])
    schemaData.value = schema
    applySettingsToForm(cfg)
  } catch (err) {
    message.error(err?.message || '加载设置失败')
  } finally {
    isLoading.value = false
  }
}

async function handleSave() {
  if (!isAdmin.value) {
    message.error('仅管理员可修改设置')
    return
  }
  isSaving.value = true
  try {
    const payload = buildPayload()
    const cfg = await updateSettings(payload)
    applySettingsToForm(cfg)
    message.success('设置已保存')
  } catch (err) {
    message.error(err?.message || '保存设置失败')
  } finally {
    isSaving.value = false
  }
}

function handleReset() {
  if (!isAdmin.value) {
    message.error('仅管理员可重置设置')
    return
  }
  Modal.confirm({
    title: '确认重置',
    content: '确定要将所有运行时设置重置为默认值吗？此操作不可撤销。',
    okText: '重置',
    okType: 'danger',
    cancelText: '取消',
    async onOk() {
      isResetting.value = true
      try {
        const cfg = await resetSettings()
        applySettingsToForm(cfg)
        message.success('已重置为默认值')
      } catch (err) {
        message.error(err?.message || '重置失败')
      } finally {
        isResetting.value = false
      }
    }
  })
}

onMounted(() => {
  loadAll()
})
</script>

<template>
  <div class="settings page-section">
    <div class="settings__header">
      <h2 class="page-title">设置</h2>
      <a-space>
        <a-button :loading="isLoading" @click="loadAll">
          <template #icon><ReloadOutlined /></template>
          刷新
        </a-button>
        <a-button
          type="primary"
          :loading="isSaving"
          :disabled="!isAdmin"
          @click="handleSave"
        >
          <template #icon><SaveOutlined /></template>
          保存
        </a-button>
        <a-button
          danger
          :loading="isResetting"
          :disabled="!isAdmin"
          @click="handleReset"
        >
          <template #icon><UndoOutlined /></template>
          重置默认
        </a-button>
      </a-space>
    </div>

    <a-alert
      v-if="!isAdmin"
      class="settings__alert"
      type="info"
      show-icon
      message="当前用户非管理员，仅可查看设置；保存与重置需 admin 权限。"
    />

    <a-spin :spinning="isLoading">
      <a-tabs v-model:activeKey="activeTab">
        <a-tab-pane key="models" tab="模型配置">
          <div class="settings__cards">
            <a-card
              v-for="key in modelKeys"
              :key="key"
              class="settings__card"
              :body-style="{ padding: '16px 18px' }"
            >
              <template #title>
                <div class="settings__card-title">
                  <span
                    class="settings__card-icon"
                    :style="{ background: modelMeta[key].color }"
                  >
                    <component :is="modelMeta[key].icon" />
                  </span>
                  <div class="settings__card-head">
                    <div class="settings__card-name">{{ modelMeta[key].label }}</div>
                    <div class="settings__card-desc">{{ modelMeta[key].desc }}</div>
                  </div>
                </div>
              </template>
              <a-form layout="vertical" :colon="false">
                <a-form-item label="provider">
                  <a-radio-group v-model:value="form.models[key].provider" button-style="solid">
                    <a-radio
                      v-for="opt in llmProviderOptions"
                      :key="opt.value"
                      :value="opt.value"
                    >
                      {{ opt.label }}
                    </a-radio>
                  </a-radio-group>
                </a-form-item>
                <a-row :gutter="12">
                  <a-col :span="24">
                    <a-form-item label="base_url">
                      <a-input
                        v-model:value="form.models[key].base_url"
                        placeholder="例如 http://localhost:11434"
                        allow-clear
                      />
                    </a-form-item>
                  </a-col>
                </a-row>
                <a-form-item
                  v-if="form.models[key].provider !== 'ollama'"
                  label="api_key"
                >
                  <a-input-password
                    v-model:value="form.models[key].api_key"
                    placeholder="无则留空"
                    allow-clear
                  >
                    <template #prefix><LockOutlined /></template>
                  </a-input-password>
                </a-form-item>
                <a-row :gutter="12">
                  <a-col :span="14">
                    <a-form-item label="model">
                      <a-input
                        v-model:value="form.models[key].model"
                        placeholder="例如 qwen3:1.7b"
                        allow-clear
                      />
                    </a-form-item>
                  </a-col>
                  <a-col :span="10">
                    <a-form-item label="timeout (秒)">
                      <a-input-number
                        v-model:value="form.models[key].timeout"
                        :min="1"
                        style="width: 100%"
                      />
                    </a-form-item>
                  </a-col>
                </a-row>
                <a-form-item label="temperature">
                  <a-input-number
                    v-model:value="form.models[key].temperature"
                    :min="0"
                    :max="2"
                    :step="0.1"
                    style="width: 100%"
                  />
                </a-form-item>
              </a-form>
            </a-card>
          </div>
        </a-tab-pane>

        <a-tab-pane key="parsers" tab="解析插件">
          <a-form layout="vertical" class="settings__parsers">
            <a-form-item label="OCR 插件">
              <a-select
                v-model:value="form.parsers.ocr.plugin"
                :options="ocrPluginOptions"
                placeholder="选择 OCR 插件"
                allow-clear
              />
            </a-form-item>
            <a-form-item label="PDF 插件">
              <a-select
                v-model:value="form.parsers.pdf.plugin"
                :options="pdfPluginOptions"
                placeholder="选择 PDF 插件"
                allow-clear
              />
            </a-form-item>
            <a-form-item label="DOCX 插件">
              <a-select
                v-model:value="form.parsers.docx.plugin"
                :options="docxPluginOptions"
                placeholder="选择 DOCX 插件"
                allow-clear
              />
            </a-form-item>
          </a-form>
        </a-tab-pane>

        <a-tab-pane key="dedup" tab="去重策略">
          <a-form layout="vertical" class="settings__dedup">
            <a-form-item label="strategy">
              <a-select
                v-model:value="form.dedup.strategy"
                :options="dedupStrategyOptions"
                placeholder="选择去重策略"
              />
            </a-form-item>
            <a-form-item label="simhash_threshold (0~64)">
              <a-input-number
                v-model:value="form.dedup.simhash_threshold"
                :min="0"
                :max="64"
                :disabled="!isSimhash"
                style="width: 100%"
              />
              <span v-if="!isSimhash" class="text-muted" style="margin-top: 4px; display: inline-block">
                仅 strategy=simhash 时启用
              </span>
            </a-form-item>
            <a-form-item label="ttl_seconds">
              <a-input-number
                v-model:value="form.dedup.ttl_seconds"
                :min="0"
                style="width: 100%"
              />
            </a-form-item>
          </a-form>
        </a-tab-pane>
      </a-tabs>
    </a-spin>
  </div>
</template>

<style scoped>
.settings__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
}

.settings__alert {
  margin-bottom: 12px;
}

.settings__cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 16px;
}

.settings__card {
  border-radius: 8px;
  border: 1px solid #e5e7eb;
  transition: box-shadow 0.2s;
}

.settings__card:hover {
  box-shadow: 0 4px 12px rgba(0, 21, 41, 0.06);
}

.settings__card :deep(.ant-card-head) {
  padding: 12px 16px;
  border-bottom: 1px solid #f0f0f0;
  min-height: auto;
}

.settings__card-title {
  display: flex;
  align-items: center;
  gap: 10px;
}

.settings__card-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 6px;
  color: #fff;
  font-size: 16px;
  flex: 0 0 auto;
}

.settings__card-head {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.settings__card-name {
  font-size: 14px;
  font-weight: 600;
  color: #1f2937;
  line-height: 1.2;
}

.settings__card-desc {
  font-size: 12px;
  color: #6b7280;
  line-height: 1.2;
}

.settings__parsers,
.settings__dedup {
  max-width: 480px;
}
</style>
