import { computed, ref } from 'vue'
import { testModelConnectivity } from '../../services/settings.js'
import { useToast } from '../../composables/useToast.js'
import EnterpriseSelect from '../../components/shared/EnterpriseSelect.vue'
import {
  CUSTOM_OPENAI_PROVIDER,
  MODEL_SECRET_MASK,
  MODEL_TYPE_LABELS,
  MODEL_TYPE_OPTIONS,
  getProviderEndpoint,
  getRerankerEndpoint,
  isModelSecretMask,
  normalizeLlmModelRows,
  normalizeProviderValue,
  normalizeValue
} from '../../utils/settingsModelHelper.js'

const FIXED_MODEL_SLOTS = new Set(['main', 'backup', 'embedding', 'reranker'])
const MODEL_TYPE_CAPABILITY = Object.fromEntries(
  MODEL_TYPE_OPTIONS.map((option) => [option.value, option.capability])
)

function buildEmptyModelDraft() {
  return {
    slot: '',
    provider: CUSTOM_OPENAI_PROVIDER,
    url: '',
    apiKey: '',
    apiKeyConfigured: false,
    modelId: '',
    type: 'llm'
  }
}

function generateModelSlot(type) {
  const prefix = type === 'embedding' ? 'embedding' : type === 'rerank' ? 'rerank' : 'llm'
  const suffix = `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 7)}`
  return `${prefix}_${suffix}`
}

function normalizeDraftModel(draft) {
  return normalizeLlmModelRows([
    {
      slot: draft.slot || generateModelSlot(draft.type),
      provider: draft.provider,
      url: draft.url,
      apiKey: draft.apiKey,
      apiKeyConfigured: draft.apiKeyConfigured,
      modelId: draft.modelId,
      type: draft.type
    }
  ])[0]
}

export default {
  name: 'LlmSettingsPanel',
  components: {
    EnterpriseSelect
  },
  props: {
    llmForm: {
      type: Object,
      required: true
    },
    providerOptions: {
      type: Array,
      required: true
    }
  },
  setup(props) {
    const { toast } = useToast()
    const modelTestState = ref({})
    const modelDialogOpen = ref(false)
    const editingSlot = ref('')
    const modelDraft = ref(buildEmptyModelDraft())

    const modelRows = computed(() => normalizeLlmModelRows(props.llmForm.models))
    const isEditingFixedModel = computed(() => isFixedModelSlot(editingSlot.value))

    function replaceModelRows(rows) {
      props.llmForm.models = normalizeLlmModelRows(rows)
    }

    function getModelTypeLabel(type) {
      return MODEL_TYPE_LABELS[type] || MODEL_TYPE_LABELS.llm
    }

    function isFixedModelSlot(slot) {
      return FIXED_MODEL_SLOTS.has(String(slot || ''))
    }

    function getModelTestState(slot) {
      return modelTestState.value[slot] || { status: 'idle', message: '' }
    }

    function isModelTesting(slot) {
      return getModelTestState(slot).status === 'testing'
    }

    function openAddModelDialog() {
      editingSlot.value = ''
      modelDraft.value = buildEmptyModelDraft()
      modelDialogOpen.value = true
    }

    function openEditModelDialog(model) {
      editingSlot.value = model.slot
      modelDraft.value = { ...model }
      modelDialogOpen.value = true
    }

    function closeModelDialog() {
      modelDialogOpen.value = false
      editingSlot.value = ''
      modelDraft.value = buildEmptyModelDraft()
    }

    function applyProviderPresetToDraft() {
      const provider = normalizeProviderValue(modelDraft.value.provider, CUSTOM_OPENAI_PROVIDER)
      modelDraft.value.provider = provider
      modelDraft.value.url =
        modelDraft.value.type === 'rerank' ? getRerankerEndpoint(provider) : getProviderEndpoint(provider)
    }

    function selectDraftModelType(type) {
      if (isEditingFixedModel.value) {
        return
      }

      modelDraft.value.type = type
      applyProviderPresetToDraft()
    }

    function clearDraftSecretMask() {
      if (isModelSecretMask(modelDraft.value.apiKey)) {
        modelDraft.value.apiKey = ''
      }
    }

    function validateDraftModel() {
      const provider = normalizeValue(modelDraft.value.provider)
      const url = normalizeValue(modelDraft.value.url)
      const modelId = normalizeValue(modelDraft.value.modelId)

      if (!provider || !url || !modelId) {
        toast('请完整填写供应商、接口地址和 model_id。')
        return false
      }

      return true
    }

    function saveModelDialog() {
      if (!validateDraftModel()) {
        return
      }

      const nextModel = normalizeDraftModel(modelDraft.value)
      const rows = [...modelRows.value]
      const currentIndex = rows.findIndex((model) => model.slot === editingSlot.value)

      if (currentIndex >= 0) {
        rows.splice(currentIndex, 1, nextModel)
      } else {
        rows.push(nextModel)
      }

      replaceModelRows(rows)
      closeModelDialog()
    }

    function removeModel(model) {
      if (isFixedModelSlot(model.slot)) {
        toast('内置运行时槽位不能删除。')
        return
      }

      if (typeof window !== 'undefined' && !window.confirm('确定删除这个模型配置吗？')) {
        return
      }

      replaceModelRows(modelRows.value.filter((row) => row.slot !== model.slot))
    }

    async function testModelConnection(model) {
      if (!normalizeValue(model.provider) || !normalizeValue(model.modelId) || !normalizeValue(model.url)) {
        const message = '请先完整填写模型的供应商、model_id 和接口地址。'
        modelTestState.value[model.slot] = { status: 'error', message }
        toast(message)
        return
      }

      modelTestState.value[model.slot] = { status: 'testing', message: '正在测试模型连通性...' }

      const payload = {
        provider: model.provider,
        model: model.modelId,
        endpoint: model.url,
        api_key: model.apiKey === MODEL_SECRET_MASK ? '' : model.apiKey,
        capability: MODEL_TYPE_CAPABILITY[model.type] || 'chat',
        slot: model.slot
      }

      try {
        const result = await testModelConnectivity(payload)
        modelTestState.value[model.slot] = {
          status: result.ok ? 'success' : 'error',
          message: result.detail || (result.ok ? '模型连接成功。' : '模型连接失败。')
        }
        toast(modelTestState.value[model.slot].message)
      } catch (error) {
        const message = error.message || '模型测试请求失败，请确认 FastAPI 已启动。'
        modelTestState.value[model.slot] = { status: 'error', message }
        toast(message)
      }
    }

    return {
      MODEL_TYPE_OPTIONS,
      applyProviderPresetToDraft,
      clearDraftSecretMask,
      closeModelDialog,
      getModelTestState,
      getModelTypeLabel,
      isEditingFixedModel,
      isFixedModelSlot,
      isModelTesting,
      modelDialogOpen,
      modelDraft,
      modelRows,
      openAddModelDialog,
      openEditModelDialog,
      removeModel,
      saveModelDialog,
      selectDraftModelType,
      testModelConnection
    }
  }
}
