import { computed, onMounted, ref } from 'vue'
import { settingsApi, type LLMConfig, type LLMModelConfig, type LLMType, type SchedulerConfig } from '@/api/settings'

type ToastState = {
  show: boolean
  message: string
  type: 'success' | 'error'
}

type EditingSnapshot = {
  type: string
  index: number
  data: LLMModelConfig
}

type ProfileState = {
  email: string
  full_name: string
  created_at: string
}

function cloneLLMConfig(config: LLMConfig): LLMConfig {
  return JSON.parse(JSON.stringify(config)) as LLMConfig
}

function cloneSchedulerConfig(config: SchedulerConfig): SchedulerConfig {
  return JSON.parse(JSON.stringify(config)) as SchedulerConfig
}

function getErrorMessage(error: unknown, fallback: string) {
  return (error as { response?: { data?: { detail?: string } } })?.response?.data?.detail || fallback
}

export function useSettingsView() {
  const loading = ref(false)
  const saving = ref(false)
  const savingModel = ref<string | null>(null)
  const toast = ref<ToastState>({
    show: false,
    message: '',
    type: 'success',
  })

  const expandedRow = ref<string | null>(null)
  const editingSnapshot = ref<EditingSnapshot | null>(null)

  const profile = ref<ProfileState>({
    email: '',
    full_name: '',
    created_at: '',
  })
  const originalProfile = ref({ email: '', full_name: '' })
  const newPassword = ref('')

  const llmConfig = ref<LLMConfig>({
    chat: [],
    vlm: [],
    embedding: [],
    rerank: [],
  })
  const originalLlmConfig = ref<LLMConfig>({
    chat: [],
    vlm: [],
    embedding: [],
    rerank: [],
  })

  const schedulerConfig = ref<SchedulerConfig>({
    daily_plan_time: '08:00',
    forum_scan_interval_minutes: 30,
    todo_ai_generate_time: '08:00',
    enabled: true,
  })
  const originalSchedulerConfig = ref<SchedulerConfig>({})

  const showRequiredWarning = computed(() => {
    return (llmConfig.value.chat?.length || 0) === 0 ||
      (llmConfig.value.embedding?.length || 0) === 0 ||
      (llmConfig.value.rerank?.length || 0) === 0
  })

  const isProfileDirty = computed(() => {
    return profile.value.full_name !== originalProfile.value.full_name || newPassword.value !== ''
  })

  const isSchedulerDirty = computed(() => {
    return JSON.stringify(schedulerConfig.value) !== JSON.stringify(originalSchedulerConfig.value)
  })

  function showToast(message: string, type: 'success' | 'error' = 'success') {
    toast.value = { show: true, message, type }
    window.setTimeout(() => {
      toast.value.show = false
    }, 3000)
  }

  function createEmptyModel(type: string): LLMModelConfig {
    return {
      name: `${type.toUpperCase()}-${Date.now()}`,
      provider: 'openai',
      model: type === 'chat'
        ? 'gpt-4o'
        : type === 'vlm'
          ? 'gpt-4o'
          : type === 'embedding'
            ? 'text-embedding-3-small'
            : 'bge-reranker-v2',
      base_url: '',
      api_key: '',
      enabled: true,
    }
  }

  function getRowKey(type: string, index: number): string {
    return `${type}-${index}`
  }

  function addModel(type: string) {
    if (!llmConfig.value[type as keyof LLMConfig]) {
      llmConfig.value[type as keyof LLMConfig] = []
    }

    if ((type === 'embedding' || type === 'rerank') &&
      llmConfig.value[type as keyof LLMConfig]!.length >= 1) {
      showToast(`${type === 'embedding' ? 'Embedding' : 'Rerank'} 最多配置 1 个`, 'error')
      return
    }

    const newModel = createEmptyModel(type)
    llmConfig.value[type as keyof LLMConfig]!.push(newModel)
    const newIndex = llmConfig.value[type as keyof LLMConfig]!.length - 1
    expandedRow.value = getRowKey(type, newIndex)
    editingSnapshot.value = { type, index: newIndex, data: JSON.parse(JSON.stringify(newModel)) as LLMModelConfig }
  }

  async function removeModel(type: string, index: number) {
    if ((type === 'embedding' || type === 'rerank') &&
      llmConfig.value[type as keyof LLMConfig]!.length <= 1) {
      showToast(`${type === 'embedding' ? 'Embedding' : 'Rerank'} 为知识库必填，至少保留 1 个`, 'error')
      return
    }

    llmConfig.value[type as keyof LLMConfig]!.splice(index, 1)
    expandedRow.value = null
    editingSnapshot.value = null

    try {
      await settingsApi.updateLLM(llmConfig.value)
      originalLlmConfig.value = cloneLLMConfig(llmConfig.value)
      showToast('删除成功')
    } catch (error: unknown) {
      showToast(getErrorMessage(error, '删除失败'), 'error')
    }
  }

  function toggleRow(type: string, index: number, model: LLMModelConfig) {
    const key = getRowKey(type, index)
    if (expandedRow.value === key) {
      expandedRow.value = null
      editingSnapshot.value = null
    } else {
      editingSnapshot.value = { type, index, data: JSON.parse(JSON.stringify(model)) as LLMModelConfig }
      expandedRow.value = key
    }
  }

  function updateModel(type: string, index: number, model: LLMModelConfig) {
    llmConfig.value[type as keyof LLMConfig]![index] = model
  }

  async function loadSettings() {
    loading.value = true
    try {
      const response = await settingsApi.get()
      profile.value = {
        email: response.data.profile.email,
        full_name: response.data.profile.full_name || '',
        created_at: response.data.profile.created_at,
      }
      originalProfile.value = { email: profile.value.email, full_name: profile.value.full_name }

      if (response.data.llm_config) {
        llmConfig.value = {
          chat: response.data.llm_config.chat || [],
          vlm: response.data.llm_config.vlm || [],
          embedding: response.data.llm_config.embedding || [],
          rerank: response.data.llm_config.rerank || [],
        }
      } else {
        llmConfig.value = { chat: [], vlm: [], embedding: [], rerank: [] }
      }
      originalLlmConfig.value = cloneLLMConfig(llmConfig.value)

      if (response.data.scheduler_config && Object.keys(response.data.scheduler_config).length > 0) {
        schedulerConfig.value = response.data.scheduler_config as SchedulerConfig
      }
      originalSchedulerConfig.value = cloneSchedulerConfig(schedulerConfig.value)
    } catch (error) {
      console.error('加载设置失败', error)
      showToast('加载设置失败', 'error')
    } finally {
      loading.value = false
    }
  }

  async function saveProfile() {
    saving.value = true
    try {
      await settingsApi.updateProfile({
        full_name: profile.value.full_name,
        password: newPassword.value || undefined,
      })
      originalProfile.value = { email: profile.value.email, full_name: profile.value.full_name }
      newPassword.value = ''
      showToast('资料保存成功')
    } catch (error: unknown) {
      showToast(getErrorMessage(error, '保存失败'), 'error')
    } finally {
      saving.value = false
    }
  }

  async function saveModel(type: string, index: number, model: LLMModelConfig) {
    const key = getRowKey(type, index)
    llmConfig.value[type as keyof LLMConfig]![index] = JSON.parse(JSON.stringify(model)) as LLMModelConfig
    savingModel.value = key

    try {
      await settingsApi.updateLLM(llmConfig.value)
      originalLlmConfig.value = cloneLLMConfig(llmConfig.value)
      expandedRow.value = null
      editingSnapshot.value = null
      showToast('保存成功')
    } catch (error: unknown) {
      showToast(getErrorMessage(error, '保存失败'), 'error')
    } finally {
      savingModel.value = null
    }
  }

  async function testModel(type: string, index: number, model: LLMModelConfig) {
    try {
      const response = await settingsApi.testLLM({
        type: type as LLMType,
        provider: model.provider,
        model: model.model,
        base_url: model.base_url,
        api_key: model.api_key,
      })

      if (response.data.success) {
        llmConfig.value[type as keyof LLMConfig]![index].enabled = true
        showToast('连接成功')
      } else {
        llmConfig.value[type as keyof LLMConfig]![index].enabled = false
        showToast(`连接失败: ${response.data.error}`, 'error')
      }
    } catch (error) {
      llmConfig.value[type as keyof LLMConfig]![index].enabled = false
      showToast('测试连接失败', 'error')
    }
  }

  async function saveScheduler() {
    saving.value = true
    try {
      await settingsApi.updateScheduler(schedulerConfig.value)
      originalSchedulerConfig.value = cloneSchedulerConfig(schedulerConfig.value)
      showToast('定时任务配置保存成功')
    } catch (error: unknown) {
      showToast(getErrorMessage(error, '保存失败'), 'error')
    } finally {
      saving.value = false
    }
  }

  function resetProfile() {
    profile.value.full_name = originalProfile.value.full_name
    newPassword.value = ''
  }

  function resetScheduler() {
    schedulerConfig.value = cloneSchedulerConfig(originalSchedulerConfig.value)
  }

  onMounted(loadSettings)

  return {
    loading,
    saving,
    savingModel,
    toast,
    expandedRow,
    editingSnapshot,
    showRequiredWarning,
    profile,
    newPassword,
    llmConfig,
    schedulerConfig,
    isProfileDirty,
    isSchedulerDirty,
    addModel,
    removeModel,
    getRowKey,
    toggleRow,
    updateModel,
    saveProfile,
    saveModel,
    testModel,
    saveScheduler,
    resetProfile,
    resetScheduler,
  }
}
