<template>
  <section class="panel">
    <div class="panel-header">
      <h2>{{ $t('settings.panelKnowledge') }}</h2>
    </div>
    <div class="general-settings">
      <SettingRow ref="rowAutoExtract" :label="$t('settings.labelAutoExtract')" :desc="$t('settings.descAutoExtract')">
        <label class="toggle">
          <input type="checkbox" v-model="knowledgeConfig.auto_extract" @change="markSaved('autoExtract')" />
          <span class="toggle-slider"></span>
        </label>
      </SettingRow>
      <SettingRow ref="rowTriggerMode" :label="$t('settings.labelTriggerMode')" :desc="$t('settings.descTriggerMode')">
        <select v-model="knowledgeConfig.trigger_mode" class="setting-select" @change="markSaved('triggerMode')">
          <option value="on_complete">{{ $t('settings.triggerOnComplete') }}</option>
          <option value="manual_only">{{ $t('settings.triggerManualOnly') }}</option>
        </select>
      </SettingRow>
      <SettingRow ref="rowMinMessages" :label="$t('settings.labelMinMessages')" :desc="$t('settings.descMinMessages')">
        <input type="number" min="2" max="50" v-model.number="knowledgeConfig.min_messages" class="setting-number" style="width:80px" @change="markSaved('minMessages')" />
      </SettingRow>
      <SettingRow ref="rowAutoInject" :label="$t('settings.labelAutoInject')" :desc="$t('settings.descAutoInject')">
        <label class="toggle">
          <input type="checkbox" v-model="knowledgeConfig.auto_inject" @change="markSaved('autoInject')" />
          <span class="toggle-slider"></span>
        </label>
      </SettingRow>
      <SettingRow ref="rowVectorEnabled" :label="$t('settings.labelVectorEnabled')" :desc="$t('settings.descVectorEnabled')">
        <label class="toggle">
          <input type="checkbox" v-model="knowledgeConfig.vector_enabled" @change="markSaved('vectorEnabled')" />
          <span class="toggle-slider"></span>
        </label>
      </SettingRow>
      <SettingRow v-if="knowledgeConfig.vector_enabled" ref="rowEmbeddingProvider" :label="$t('settings.labelEmbeddingProvider')" :desc="$t('settings.descEmbeddingProvider')">
        <select v-model="knowledgeConfig.embedding_provider_id" class="setting-select" @change="markSaved('embeddingProvider')">
          <option :value="null">{{ $t('settings.embeddingProviderNone') }}</option>
          <option v-for="p in embeddingProviders" :key="p.id" :value="p.id">{{ p.name }}</option>
        </select>
      </SettingRow>
      <SettingRow v-if="knowledgeConfig.vector_enabled" ref="rowEmbeddingModel" :label="$t('settings.labelEmbeddingModel')" :desc="$t('settings.descEmbeddingModel')">
        <input type="text" :value="knowledgeConfig.embedding_model ?? ''" @input="knowledgeConfig.embedding_model = ($event.target as HTMLInputElement).value || null" @change="markSaved('embeddingModel')" class="setting-input" :placeholder="$t('settings.phEmbeddingModel')" style="width:220px" />
      </SettingRow>
    </div>
  </section>
</template>

<script setup lang="ts">
import { reactive, computed, watch, onMounted, onUnmounted, useTemplateRef } from 'vue'
import { knowledgeApi } from '@/api'
import type { AiProviderConfig } from '@/api/types'
import SettingRow from './SettingRow.vue'

// ============================================================
// 知识库配置域(提取 + 注入) — 走后端 IPC,非 localStorage
// 阶段5:SettingRow 封装行布局,控件变更后调 markSaved 显"已保存"(用户 @change 触发,
//        与 watch 深响应 debounce 保存解耦,启动 load 不显)
// ============================================================
const props = defineProps<{
  /** Provider 列表(embedding provider 下拉依赖,由 ProviderPanel 上浮同步) */
  aiProviders: AiProviderConfig[]
}>()

const knowledgeConfig = reactive({
  loaded: false,
  auto_extract: true,
  trigger_mode: 'on_complete' as 'on_complete' | 'manual_only',
  min_messages: 4,
  auto_inject: true,
  vector_enabled: false,
  embedding_provider_id: null as string | null,
  embedding_model: null as string | null,
})

// 可做 embedding 的 provider(仅 openai_compat,Anthropic 无 embed API)
const embeddingProviders = computed(() =>
  props.aiProviders.filter(p => p.provider_type !== 'anthropic')
)

async function loadKnowledgeConfig() {
  try {
    const cfg = await knowledgeApi.getConfig()
    Object.assign(knowledgeConfig, cfg)
    knowledgeConfig.loaded = true
  } catch (e) {
    console.error('加载知识库配置失败:', e)
  }
}

// M33: 跟踪待反馈的行 key——@change 触发 markSaved 不再立即显「已保存」,
// 改为记下 key,等真正 IPC saveConfig resolve 后才显,防假成功(乐观 UI 误导)。
let _pendingSavedKey: SavedKey | null = null
let _knowledgeSaveTimer: ReturnType<typeof setTimeout> | null = null
function saveKnowledgeConfigDebounced() {
  if (_knowledgeSaveTimer) clearTimeout(_knowledgeSaveTimer)
  _knowledgeSaveTimer = setTimeout(async () => {
    try {
      const { loaded, ...cfg } = knowledgeConfig
      void loaded
      // cfg 形态与后端 KnowledgeConfig 对齐(auto_extract/trigger_mode/min_messages/
      // auto_inject/vector_enabled/embedding_provider_id/embedding_model),无需 as any
      await knowledgeApi.saveConfig(cfg)
      // M33: IPC 成功后才显「已保存」(防假成功)。失败走 catch 不显,避免误导。
      if (_pendingSavedKey) flashRow(_pendingSavedKey)
    } catch (e) {
      console.error('保存知识库配置失败:', e)
      // M33: 失败时不显「已保存」;后端错误已 console,前端无行级错误态(对齐原实现,
      // 原实现也只是吞错)。如需更明显反馈可在此 emit toast,但本任务范围只防假成功。
    } finally {
      _pendingSavedKey = null
    }
  }, 500)
}

watch(
  () => ({ ...knowledgeConfig }),
  () => {
    if (knowledgeConfig.loaded) saveKnowledgeConfigDebounced()
  },
  { deep: true },
)

// 即时生效反馈:SettingRow refs(embedding 两项 v-if 条件渲染,可能未挂载,?. 安全)
const rowAutoExtract = useTemplateRef<InstanceType<typeof SettingRow>>('rowAutoExtract')
const rowTriggerMode = useTemplateRef<InstanceType<typeof SettingRow>>('rowTriggerMode')
const rowMinMessages = useTemplateRef<InstanceType<typeof SettingRow>>('rowMinMessages')
const rowAutoInject = useTemplateRef<InstanceType<typeof SettingRow>>('rowAutoInject')
const rowVectorEnabled = useTemplateRef<InstanceType<typeof SettingRow>>('rowVectorEnabled')
const rowEmbeddingProvider = useTemplateRef<InstanceType<typeof SettingRow>>('rowEmbeddingProvider')
const rowEmbeddingModel = useTemplateRef<InstanceType<typeof SettingRow>>('rowEmbeddingModel')
type SavedKey = 'autoExtract' | 'triggerMode' | 'minMessages' | 'autoInject' | 'vectorEnabled' | 'embeddingProvider' | 'embeddingModel'

/**
 * M33: @change 触发入口——不立即显「已保存」,先记 pending key,
 * 等 saveKnowledgeConfigDebounced 内 IPC saveConfig 成功后调 flashRow 显反馈(防假成功)。
 * 连续多字段改动时取最后一次 key(用户视线所在),旧 key 反馈被新 key 覆盖可接受。
 */
function markSaved(key: SavedKey) {
  _pendingSavedKey = key
}

/** 真正点亮行内「✓已保存」反馈(仅 IPC 成功路径调用)。 */
function flashRow(key: SavedKey) {
  const map: Record<SavedKey, InstanceType<typeof SettingRow> | null> = {
    autoExtract: rowAutoExtract.value,
    triggerMode: rowTriggerMode.value,
    minMessages: rowMinMessages.value,
    autoInject: rowAutoInject.value,
    vectorEnabled: rowVectorEnabled.value,
    embeddingProvider: rowEmbeddingProvider.value,
    embeddingModel: rowEmbeddingModel.value,
  }
  map[key]?.markSaved()
}

onMounted(() => {
  loadKnowledgeConfig()
})

// 组件卸载清 debounce timer,防 unmount 后旧 timer 仍 fire 写已销毁 reactive(timer 泄漏 FR-C3)
onUnmounted(() => {
  if (_knowledgeSaveTimer) clearTimeout(_knowledgeSaveTimer)
})
</script>

<style scoped>
/* 阶段1 UX 重构:共用样式抽至 src/components/settings/settings.css 全局。
   阶段5:行布局封装进 SettingRow(本 Panel 无特有 scoped 样式)。 */
</style>
