import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { settingsApi } from '@/api/settings'
import type {
  ILlmConfigResponse,
  ILlmConfigUpdate,
  ILlmProviderUpdate,
  ISkillsConfigUpdate,
  IKbConfigResponse,
  IKbConfigUpdate,
  IGeneralConfigResponse,
  IGeneralConfigUpdate,
} from '@/api/settings'

export interface ILLMSettings {
  provider: string
  model: string
  api_key: string
  base_url: string
}

export interface ISkillSettings {
  default_skill: string
  auto_routing: boolean
  paths: string[]
}

export interface IKBSettings {
  default_sources: string[]
  top_k: number
  retrieval_mode: string
}

export interface ISystemSettings {
  rate_limit: number
  cors_origins: string[]
  logging_level: string
  host: string
  port: number
  workers: number
  log_format: string
}

export const useSettingsStore = defineStore('settings', () => {
  // --- State ---
  const llm = ref<ILLMSettings>({
    provider: '',
    model: '',
    api_key: '',
    base_url: '',
  })
  const skillSettings = ref<ISkillSettings>({
    default_skill: '',
    auto_routing: true,
    paths: [],
  })
  const kbSettings = ref<IKBSettings>({
    default_sources: [],
    top_k: 5,
    retrieval_mode: 'standard',
  })
  const system = ref<ISystemSettings>({
    rate_limit: 60,
    cors_origins: ['*'],
    logging_level: 'INFO',
    host: '0.0.0.0',
    // Default port matches agentkit.yaml (18001) and .env.dev's BACKEND_PORT.
    // Overridden at runtime when the API returns the actual configured port.
    port: Number(import.meta.env.BACKEND_PORT) || 18001,
    workers: 1,
    log_format: 'text',
  })
  const isLoading = ref(false)
  const isSaving = ref(false)
  const error = ref<string | null>(null)
  const saveSuccess = ref(false)

  // Internal: raw LLM config from API for mapping
  let _rawLlmConfig: ILlmConfigResponse | null = null

  // --- Getters ---
  const hasLLMConfig = computed(() => !!llm.value.provider && !!llm.value.model)

  // --- Actions ---

  /** Map LLM API response to store state */
  function _mapLlmResponse(data: ILlmConfigResponse): void {
    _rawLlmConfig = data
    // Use the first provider as the "active" one in the simple UI
    const firstProvider = data.providers[0]
    if (firstProvider) {
      llm.value.provider = firstProvider.name
      llm.value.api_key = firstProvider.api_key
      llm.value.base_url = firstProvider.base_url
      // Use the first model from the provider's models dict
      const modelKeys = Object.keys(firstProvider.models || {})
      llm.value.model = modelKeys[0] || ''
    }
  }

  /** Map KB API response to store state */
  function _mapKbResponse(data: IKbConfigResponse): void {
    const semantic = (data.memory?.semantic || {}) as Record<string, unknown>
    kbSettings.value.default_sources = (semantic.knowledge_base_ids as string[]) || []
    kbSettings.value.top_k = (semantic.top_k as number) ?? 5
    kbSettings.value.retrieval_mode = (semantic.search_mode as string) || 'standard'
  }

  /** Map General API response to store state */
  function _mapGeneralResponse(data: IGeneralConfigResponse): void {
    system.value.host = data.host
    system.value.port = data.port
    system.value.workers = data.workers
    system.value.logging_level = data.log_level
    system.value.log_format = data.log_format
    system.value.rate_limit = data.rate_limit
    system.value.cors_origins = data.cors_origins
  }

  async function fetchSettings(): Promise<void> {
    isLoading.value = true
    error.value = null
    try {
      // Fetch all config groups in parallel
      const [llmData, skillsData, kbData, generalData] = await Promise.allSettled([
        settingsApi.getLlmConfig(),
        settingsApi.getSkillsConfig(),
        settingsApi.getKbConfig(),
        settingsApi.getGeneralConfig(),
      ])

      if (llmData.status === 'fulfilled') {
        _mapLlmResponse(llmData.value)
      }
      if (skillsData.status === 'fulfilled') {
        skillSettings.value.paths = skillsData.value.paths
        skillSettings.value.auto_routing = skillsData.value.auto_discover
      }
      if (kbData.status === 'fulfilled') {
        _mapKbResponse(kbData.value)
      }
      if (generalData.status === 'fulfilled') {
        _mapGeneralResponse(generalData.value)
      }
    } catch (err) {
      error.value = err instanceof Error ? err.message : '加载设置失败'
      console.warn('Failed to fetch settings:', err)
    } finally {
      isLoading.value = false
    }
  }

  async function saveSettings(): Promise<void> {
    isSaving.value = true
    error.value = null
    saveSuccess.value = false
    try {
      // Build LLM update payload
      const providerUpdate: ILlmProviderUpdate = {
        name: llm.value.provider,
        type: llm.value.provider, // type defaults to provider name convention
        api_key: llm.value.api_key || null,
        base_url: llm.value.base_url,
      }
      if (llm.value.model) {
        providerUpdate.models = { [llm.value.model]: {} }
      }
      const llmUpdate: ILlmConfigUpdate = {
        providers: [providerUpdate],
      }
      // Preserve model_aliases and fallbacks from raw config if available
      if (_rawLlmConfig) {
        llmUpdate.model_aliases = _rawLlmConfig.model_aliases
        llmUpdate.fallbacks = _rawLlmConfig.fallbacks
      }

      // Build skills update payload
      const skillsUpdate: ISkillsConfigUpdate = {
        paths: skillSettings.value.paths,
        auto_discover: skillSettings.value.auto_routing,
      }

      // Build KB update payload
      const kbUpdate: IKbConfigUpdate = {
        memory: {
          semantic: {
            enabled: kbSettings.value.default_sources.length > 0,
            knowledge_base_ids: kbSettings.value.default_sources,
            top_k: kbSettings.value.top_k,
            search_mode: kbSettings.value.retrieval_mode,
          },
        },
      }

      // Build general update payload
      const generalUpdate: IGeneralConfigUpdate = {
        rate_limit: system.value.rate_limit,
        cors_origins: system.value.cors_origins,
        log_level: system.value.logging_level,
      }

      // Save all config groups in parallel
      await Promise.all([
        settingsApi.updateLlmConfig(llmUpdate),
        settingsApi.updateSkillsConfig(skillsUpdate),
        settingsApi.updateKbConfig(kbUpdate),
        settingsApi.updateGeneralConfig(generalUpdate),
      ])

      saveSuccess.value = true
      setTimeout(() => {
        saveSuccess.value = false
      }, 3000)
    } catch (err) {
      error.value = err instanceof Error ? err.message : '保存设置失败'
      console.error('Failed to save settings:', err)
      throw err
    } finally {
      isSaving.value = false
    }
  }

  return {
    // State
    llm,
    skillSettings,
    kbSettings,
    system,
    isLoading,
    isSaving,
    error,
    saveSuccess,
    // Getters
    hasLLMConfig,
    // Actions
    fetchSettings,
    saveSettings,
  }
})
