import { defineStore } from 'pinia'
import { ref } from 'vue'
import { evolutionApi } from '@/api/evolution'
import type {
  Experience,
  EvolutionMetrics,
  TrendPoint,
  PitfallWarning,
  PathOptimization,
} from '@/api/evolution'

export const useEvolutionStore = defineStore('evolution', () => {
  // --- State ---
  const experiences = ref<Experience[]>([])
  const metrics = ref<EvolutionMetrics | null>(null)
  const trends = ref<TrendPoint[]>([])
  const pitfalls = ref<PitfallWarning[]>([])
  const optimizations = ref<PathOptimization[]>([])
  const period = ref<string>('7d')
  const isLoading = ref(false)
  const error = ref<string | null>(null)

  // --- WebSocket State ---
  let wsConnection: WebSocket | null = null
  let wsReconnectCount = 0
  const WS_MAX_RECONNECT = 3
  const WS_RECONNECT_DELAY = 5000
  let wsIntentionallyClosed = false
  let wsReconnectTimer: ReturnType<typeof setTimeout> | null = null

  // --- Actions ---

  /** Load recent experiences */
  async function loadExperiences(outcome?: string): Promise<void> {
    isLoading.value = true
    error.value = null
    try {
      const data = await evolutionApi.getExperiences({
        outcome,
        limit: 50,
      })
      experiences.value = data.experiences
    } catch (err) {
      error.value = err instanceof Error ? err.message : '加载经验记录失败'
      console.error('Failed to load experiences:', err)
    } finally {
      isLoading.value = false
    }
  }

  /** Load evolution metrics */
  async function loadMetrics(periodParam?: string): Promise<void> {
    isLoading.value = true
    error.value = null
    const p = periodParam || period.value
    try {
      const data = await evolutionApi.getMetrics(p)
      metrics.value = data.metrics
      trends.value = data.trends
      period.value = p
    } catch (err) {
      error.value = err instanceof Error ? err.message : '加载指标数据失败'
      console.error('Failed to load metrics:', err)
    } finally {
      isLoading.value = false
    }
  }

  /** Check pitfall warnings */
  async function checkPitfalls(taskType: string, steps: string[]): Promise<void> {
    isLoading.value = true
    error.value = null
    try {
      const data = await evolutionApi.checkPitfalls({ task_type: taskType, steps })
      pitfalls.value = data.warnings
    } catch (err) {
      error.value = err instanceof Error ? err.message : '检查避坑预警失败'
      console.error('Failed to check pitfalls:', err)
    } finally {
      isLoading.value = false
    }
  }

  /** Load path optimization history */
  async function loadOptimizations(taskType?: string): Promise<void> {
    isLoading.value = true
    error.value = null
    try {
      const data = await evolutionApi.getPathOptimizations({
        task_type: taskType,
        limit: 20,
      })
      optimizations.value = data.optimizations
    } catch (err) {
      error.value = err instanceof Error ? err.message : '加载路径优化记录失败'
      console.error('Failed to load optimizations:', err)
    } finally {
      isLoading.value = false
    }
  }

  // --- WebSocket Actions ---

  /** Connect to WebSocket for real-time updates */
  function connectWebSocket() {
    if (wsConnection) return

    wsIntentionallyClosed = false
    const ws = evolutionApi.createWebSocket()

    ws.onopen = () => {
      wsReconnectCount = 0
      ws.send(JSON.stringify({
        type: 'subscribe',
        channels: ['experiences', 'metrics', 'pitfalls', 'optimizations'],
      }))
    }

    ws.onmessage = (event) => {
      try {
        const data = JSON.parse(event.data)
        switch (data.type) {
          case 'experience_added':
            loadExperiences()
            break
          case 'metrics_updated':
            loadMetrics(period.value)
            break
          case 'pitfall_detected':
            pitfalls.value = data.data?.warnings ?? pitfalls.value
            break
          case 'optimization_updated':
            loadOptimizations()
            break
        }
      } catch {
        // Ignore non-JSON messages
      }
    }

    ws.onclose = () => {
      wsConnection = null
      if (!wsIntentionallyClosed && wsReconnectCount < WS_MAX_RECONNECT) {
        wsReconnectCount++
        wsReconnectTimer = setTimeout(connectWebSocket, WS_RECONNECT_DELAY)
      }
    }

    ws.onerror = () => {
      ws.close()
    }

    wsConnection = ws
  }

  /** Disconnect WebSocket and prevent reconnection */
  function disconnectWebSocket() {
    wsIntentionallyClosed = true
    if (wsReconnectTimer) {
      clearTimeout(wsReconnectTimer)
      wsReconnectTimer = null
    }
    if (wsConnection) {
      wsConnection.onclose = null // prevent reconnect on intentional close
      wsConnection.close()
      wsConnection = null
    }
    wsReconnectCount = WS_MAX_RECONNECT // Prevent reconnect
  }

  return {
    // State
    experiences,
    metrics,
    trends,
    pitfalls,
    optimizations,
    period,
    isLoading,
    error,
    // Actions
    loadExperiences,
    loadMetrics,
    checkPitfalls,
    loadOptimizations,
    connectWebSocket,
    disconnectWebSocket,
  }
})
