import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import type { StatusUpdate, Theme, Toast, InfoResponse, RoutingInfo } from '@/types'
import api from '@/services/api'

export const useSystemStore = defineStore('system', () => {
  // State
  const status = ref<StatusUpdate | null>(null)
  const eventSource = ref<EventSource | null>(null)
  const connected = ref(false)
  const currentTheme = ref<string>('corporate')
  const sidebarCollapsed = ref<boolean>(
    (() => {
      try {
        return localStorage.getItem('mcpproxy-sidebar-collapsed') === '1'
      } catch {
        return false
      }
    })()
  )
  const toasts = ref<Toast[]>([])
  const info = ref<InfoResponse | null>(null)
  const routing = ref<RoutingInfo | null>(null)
  const checkingForUpdates = ref(false)
  const updateCheckedAt = ref<string | null>(null)

  // Available themes
  const themes: Theme[] = [
    { name: 'light', displayName: 'Light', dark: false },
    { name: 'dark', displayName: 'Dark', dark: true },
    { name: 'corporate', displayName: 'Corporate', dark: false },
    { name: 'business', displayName: 'Business', dark: true },
    { name: 'emerald', displayName: 'Emerald', dark: false },
    { name: 'forest', displayName: 'Forest', dark: true },
    { name: 'aqua', displayName: 'Aqua', dark: false },
    { name: 'lofi', displayName: 'Lo-Fi', dark: false },
    { name: 'pastel', displayName: 'Pastel', dark: false },
    { name: 'fantasy', displayName: 'Fantasy', dark: false },
    { name: 'wireframe', displayName: 'Wireframe', dark: false },
    { name: 'luxury', displayName: 'Luxury', dark: true },
    { name: 'dracula', displayName: 'Dracula', dark: true },
    { name: 'synthwave', displayName: 'Synthwave', dark: true },
    { name: 'cyberpunk', displayName: 'Cyberpunk', dark: true },
  ]

  // Computed
  const isRunning = computed(() => {
    // Priority: Top-level running field, then nested status.running, default false
    if (status.value?.running !== undefined) {
      return status.value.running
    }
    // Fallback to nested status.running if top-level is undefined
    if (status.value?.status?.running !== undefined) {
      return status.value.status.running
    }
    return false
  })
  const listenAddr = computed(() => status.value?.listen_addr ?? '')
  const upstreamStats = computed(() => status.value?.upstream_stats ?? {
    connected_servers: 0,
    total_servers: 0,
    total_tools: 0,
  })

  const currentThemeConfig = computed(() =>
    themes.find(t => t.name === currentTheme.value) || themes[0]
  )

  // Version information
  const version = computed(() => info.value?.version ?? '')
  const updateAvailable = computed(() => info.value?.update?.available ?? false)
  const latestVersion = computed(() => info.value?.update?.latest_version ?? '')

  // Routing mode
  const routingMode = computed(() => routing.value?.routing_mode ?? status.value?.routing_mode ?? 'retrieve_tools')

  // Actions
  function connectEventSource() {
    if (eventSource.value) {
      eventSource.value.close()
    }

    console.log('Attempting to connect EventSource...')
    console.log('API key status:', {
      hasApiKey: api.hasAPIKey(),
      apiKeyPreview: api.getAPIKeyPreview()
    })

    const es = api.createEventSource()
    eventSource.value = es

    es.onopen = () => {
      connected.value = true
      console.log('EventSource connected successfully')
    }

    es.onmessage = (event) => {
      try {
        const data = JSON.parse(event.data) as StatusUpdate
        status.value = data

        // Debug logging to help diagnose status issues
        console.log('SSE Status Update:', {
          topLevelRunning: data.running,
          nestedStatusRunning: data.status?.running,
          listen_addr: data.listen_addr,
          timestamp: data.timestamp,
          finalRunningValue: data.running !== undefined ? data.running : (data.status?.running ?? false)
        })

        // You could emit events here for other stores to listen to
        // For example, update server statuses
      } catch (error) {
        console.error('Failed to parse SSE message:', error)
      }
    }

    // Listen specifically for status events
    es.addEventListener('status', (event) => {
      try {
        const data = JSON.parse(event.data) as StatusUpdate
        status.value = data

        // Debug logging to help diagnose status issues
        console.log('SSE Status Event Update:', {
          topLevelRunning: data.running,
          nestedStatusRunning: data.status?.running,
          listen_addr: data.listen_addr,
          timestamp: data.timestamp,
          finalRunningValue: data.running !== undefined ? data.running : (data.status?.running ?? false)
        })
      } catch (error) {
        console.error('Failed to parse SSE status event:', error)
      }
    })

    // Listen for servers.changed events to trigger immediate UI updates
    es.addEventListener('servers.changed', (event) => {
      try {
        const data = JSON.parse(event.data)
        console.log('SSE servers.changed event received:', data)

        // Import and call serversStore.fetchServers() to refresh server list
        // Note: This creates a circular dependency, so we'll emit a custom event instead
        window.dispatchEvent(new CustomEvent('mcpproxy:servers-changed', { detail: data }))
      } catch (error) {
        console.error('Failed to parse SSE servers.changed event:', error)
      }
    })

    // Listen for config.reloaded events
    es.addEventListener('config.reloaded', (event) => {
      try {
        const data = JSON.parse(event.data)
        console.log('SSE config.reloaded event received:', data)

        // Trigger server list refresh on config reload
        window.dispatchEvent(new CustomEvent('mcpproxy:config-reloaded', { detail: data }))
      } catch (error) {
        console.error('Failed to parse SSE config.reloaded event:', error)
      }
    })

    // Listen for config.saved events to notify Configuration page
    es.addEventListener('config.saved', (event) => {
      try {
        const data = JSON.parse(event.data)
        console.log('SSE config.saved event received:', data)

        // Dispatch event for Configuration page to refresh
        window.dispatchEvent(new CustomEvent('mcpproxy:config-saved', { detail: data }))
      } catch (error) {
        console.error('Failed to parse SSE config.saved event:', error)
      }
    })

    // Listen for security.scanner_changed events so the Security page can
    // refresh the scanner list when a background image pull finishes (spec 039).
    es.addEventListener('security.scanner_changed', (event) => {
      try {
        const data = JSON.parse(event.data)
        window.dispatchEvent(new CustomEvent('mcpproxy:scanner-changed', { detail: data }))
      } catch (error) {
        console.error('Failed to parse SSE security.scanner_changed event:', error)
      }
    })

    // Spec 077 US4 (MCP-2207): a single debounced settled event per server per
    // scan replaces the per-scanner scan_started/progress/completed/failed
    // storm. Forward it so scan-status consumers can refresh once per scan.
    es.addEventListener('security.scan_settled', (event) => {
      try {
        const data = JSON.parse(event.data)
        const payload = data.payload || data
        window.dispatchEvent(new CustomEvent('mcpproxy:scan-settled', { detail: payload }))
      } catch (error) {
        console.error('Failed to parse SSE security.scan_settled event:', error)
      }
    })

    // Listen for activity events (tool calls, policy decisions, etc.)
    es.addEventListener('activity.tool_call.started', (event) => {
      try {
        const data = JSON.parse(event.data)
        console.log('SSE activity.tool_call.started event received:', data)
        // Extract payload - SSE wraps activity data in {payload: ..., timestamp: ...}
        const payload = data.payload || data
        window.dispatchEvent(new CustomEvent('mcpproxy:activity-started', { detail: payload }))
      } catch (error) {
        console.error('Failed to parse SSE activity.tool_call.started event:', error)
      }
    })

    es.addEventListener('activity.tool_call.completed', (event) => {
      try {
        const data = JSON.parse(event.data)
        console.log('SSE activity.tool_call.completed event received:', data)
        // Extract payload - SSE wraps activity data in {payload: ..., timestamp: ...}
        const payload = data.payload || data
        window.dispatchEvent(new CustomEvent('mcpproxy:activity-completed', { detail: payload }))
      } catch (error) {
        console.error('Failed to parse SSE activity.tool_call.completed event:', error)
      }
    })

    es.addEventListener('activity.policy_decision', (event) => {
      try {
        const data = JSON.parse(event.data)
        console.log('SSE activity.policy_decision event received:', data)
        // Extract payload - SSE wraps activity data in {payload: ..., timestamp: ...}
        const payload = data.payload || data
        window.dispatchEvent(new CustomEvent('mcpproxy:activity-policy', { detail: payload }))
      } catch (error) {
        console.error('Failed to parse SSE activity.policy_decision event:', error)
      }
    })

    es.addEventListener('activity', (event) => {
      try {
        const data = JSON.parse(event.data)
        console.log('SSE activity event received:', data)
        // Extract payload - SSE wraps activity data in {payload: ..., timestamp: ...}
        const payload = data.payload || data
        window.dispatchEvent(new CustomEvent('mcpproxy:activity', { detail: payload }))
      } catch (error) {
        console.error('Failed to parse SSE activity event:', error)
      }
    })

    // Listen for internal tool call events (Spec 024)
    es.addEventListener('activity.internal_tool_call.completed', (event) => {
      try {
        const data = JSON.parse(event.data)
        console.log('SSE activity.internal_tool_call.completed event received:', data)
        const payload = data.payload || data
        window.dispatchEvent(new CustomEvent('mcpproxy:activity-completed', { detail: payload }))
      } catch (error) {
        console.error('Failed to parse SSE activity.internal_tool_call.completed event:', error)
      }
    })

    // Listen for system lifecycle events (Spec 024)
    // Note: Backend sends "activity.system.start" (with dots, not underscores)
    es.addEventListener('activity.system.start', (event) => {
      try {
        const data = JSON.parse(event.data)
        console.log('SSE activity.system_start event received:', data)
        const payload = data.payload || data
        window.dispatchEvent(new CustomEvent('mcpproxy:activity', { detail: payload }))
      } catch (error) {
        console.error('Failed to parse SSE activity.system_start event:', error)
      }
    })

    // Note: Backend sends "activity.system.stop" (with dots, not underscores)
    es.addEventListener('activity.system.stop', (event) => {
      try {
        const data = JSON.parse(event.data)
        console.log('SSE activity.system_stop event received:', data)
        const payload = data.payload || data
        window.dispatchEvent(new CustomEvent('mcpproxy:activity', { detail: payload }))
      } catch (error) {
        console.error('Failed to parse SSE activity.system_stop event:', error)
      }
    })

    // Listen for config change events (Spec 024)
    es.addEventListener('activity.config_change', (event) => {
      try {
        const data = JSON.parse(event.data)
        console.log('SSE activity.config_change event received:', data)
        const payload = data.payload || data
        window.dispatchEvent(new CustomEvent('mcpproxy:activity', { detail: payload }))
      } catch (error) {
        console.error('Failed to parse SSE activity.config_change event:', error)
      }
    })

    es.onerror = (event) => {
      connected.value = false
      console.error('EventSource error occurred:', event)

      // Check if this might be an authentication error
      if (es.readyState === EventSource.CLOSED) {
        console.error('EventSource connection closed - possible authentication failure')

        // If we have an API key but still failed, try reinitializing
        if (api.hasAPIKey()) {
          console.log('Attempting to reinitialize API key and retry connection...')
          api.reinitializeAPIKey()
        }
      }

      // Retry connection after a delay
      setTimeout(() => {
        console.log('Retrying EventSource connection in 5 seconds...')
        connectEventSource()
      }, 5000)
    }
  }

  function disconnectEventSource() {
    if (eventSource.value) {
      eventSource.value.close()
      eventSource.value = null
    }
    connected.value = false
  }

  function setTheme(themeName: string) {
    const theme = themes.find(t => t.name === themeName)
    if (theme) {
      currentTheme.value = themeName
      document.documentElement.setAttribute('data-theme', themeName)
      localStorage.setItem('mcpproxy-theme', themeName)
    }
  }

  function loadTheme() {
    const savedTheme = localStorage.getItem('mcpproxy-theme')
    if (savedTheme && themes.find(t => t.name === savedTheme)) {
      setTheme(savedTheme)
    } else {
      setTheme('corporate')
    }
  }

  function toggleSidebar() {
    sidebarCollapsed.value = !sidebarCollapsed.value
    try {
      localStorage.setItem(
        'mcpproxy-sidebar-collapsed',
        sidebarCollapsed.value ? '1' : '0'
      )
    } catch {
      // localStorage unavailable (private browsing, etc.) — just keep in-memory
    }
  }

  function addToast(toast: Omit<Toast, 'id'>): string {
    const id = Math.random().toString(36).substr(2, 9)
    const newToast: Toast = {
      ...toast,
      id,
      duration: toast.duration ?? 5000,
    }

    toasts.value.push(newToast)

    // Auto-remove toast after duration
    if (newToast.duration && newToast.duration > 0) {
      setTimeout(() => {
        removeToast(id)
      }, newToast.duration)
    }

    return id
  }

  function removeToast(id: string) {
    const index = toasts.value.findIndex(t => t.id === id)
    if (index > -1) {
      toasts.value.splice(index, 1)
    }
  }

  function clearToasts() {
    toasts.value = []
  }

  async function fetchInfo() {
    try {
      const response = await api.getInfo()
      if (response.success && response.data) {
        info.value = response.data
        if (response.data.update?.checked_at) {
          updateCheckedAt.value = response.data.update.checked_at
        }
      }
    } catch (error) {
      console.error('Failed to fetch info:', error)
    }
  }

  async function checkForUpdates(): Promise<{ ok: boolean; error?: string }> {
    if (checkingForUpdates.value) return { ok: false, error: 'already checking' }
    checkingForUpdates.value = true
    try {
      const response = await api.getInfo({ refresh: true })
      if (response.success && response.data) {
        info.value = response.data
        // Spec 079 FR-015: when update checking is disabled
        // (update_check.enabled=false or MCPPROXY_DISABLE_AUTO_UPDATE), the
        // daemon performs no check and omits the update object — say so
        // instead of a misleading "latest version" toast.
        if (!response.data.update) {
          addToast({
            type: 'info',
            title: 'Update checks are disabled',
            message: 'Enable update_check in the configuration to check for updates.',
          })
          return { ok: true }
        }
        updateCheckedAt.value = response.data.update?.checked_at ?? new Date().toISOString()
        const checkErr = response.data.update?.check_error
        if (checkErr) {
          addToast({ type: 'error', title: 'Update check failed', message: checkErr })
          return { ok: false, error: checkErr }
        }
        if (response.data.update?.available) {
          addToast({
            type: 'info',
            title: 'Update available',
            message: response.data.update.latest_version || '',
          })
        } else {
          addToast({ type: 'success', title: 'You are running the latest version.' })
        }
        return { ok: true }
      }
      const err = response.error || 'Request failed'
      addToast({ type: 'error', title: 'Update check failed', message: err })
      return { ok: false, error: err }
    } catch (error) {
      const msg = error instanceof Error ? error.message : String(error)
      console.error('Failed to check for updates:', error)
      addToast({ type: 'error', title: 'Update check failed', message: msg })
      return { ok: false, error: msg }
    } finally {
      checkingForUpdates.value = false
    }
  }

  async function fetchRouting() {
    try {
      const response = await api.getRouting()
      if (response.success && response.data) {
        routing.value = response.data
      }
    } catch (error) {
      console.error('Failed to fetch routing:', error)
    }
  }

  // Initialize theme on store creation
  loadTheme()

  return {
    // State
    status,
    connected,
    currentTheme,
    toasts,
    themes,
    info,
    routing,
    checkingForUpdates,
    updateCheckedAt,

    // Computed
    isRunning,
    listenAddr,
    upstreamStats,
    currentThemeConfig,
    version,
    updateAvailable,
    latestVersion,
    routingMode,
    sidebarCollapsed,

    // Actions
    connectEventSource,
    disconnectEventSource,
    setTheme,
    loadTheme,
    toggleSidebar,
    addToast,
    removeToast,
    clearToasts,
    fetchInfo,
    fetchRouting,
    checkForUpdates,
  }
})
