import { defineStore } from 'pinia'
import { ref, onMounted } from 'vue'
import type { WipeProfile, WipeSchedule, WipeHistory } from '@/types'
import { useApi } from '@/composables/useApi'
import { useWebSocket, type WebSocketMessage } from '@/composables/useWebSocket'
import { useAuthStore } from '@/stores/auth'
import { useToastStore } from '@/stores/toast'

export const useWipeStore = defineStore('wipe', () => {
  const api = useApi()
  const authStore = useAuthStore()
  const websocket = useWebSocket()
  const toast = useToastStore()

  const profiles = ref<WipeProfile[]>([])
  const schedules = ref<WipeSchedule[]>([])
  const history = ref<WipeHistory[]>([])
  const isLoading = ref(false)
  const error = ref<string | null>(null)

  // WebSocket event handler
  function handleWebSocketMessage(message: WebSocketMessage) {
    if (message.type !== 'event') return

    const { event, data } = message

    switch (event) {
      case 'wipe_started':
        // Update wipe history with new status
        if (data?.wipe_history_id) {
          updateWipeHistoryItem(data)
        }
        toast.info(`Wipe started: ${data?.wipe_type || 'unknown'} wipe in progress`)
        break

      case 'wipe_status':
        // Update wipe history with status progress
        if (data?.wipe_history_id) {
          updateWipeHistoryItem(data)
        }
        break

      case 'wipe_completed':
        toast.success(`Wipe completed successfully in ${data?.duration || '?'} seconds`)
        // Refresh history to get final state
        fetchHistory().catch(console.error)
        break

      case 'wipe_failed':
        toast.error(`Wipe failed: ${data?.error_message || 'Unknown error'}`, 10000)
        // Refresh history to get final state
        fetchHistory().catch(console.error)
        break

      default:
        // Ignore other events
        break
    }
  }

  // Update a single wipe history item from WebSocket data
  function updateWipeHistoryItem(data: any) {
    const id = data.wipe_history_id || data.id
    if (!id) return

    const index = history.value.findIndex(h => h.id === id)
    if (index !== -1 && history.value[index]) {
      // Update existing item (merge partial data)
      const current = history.value[index]

      // Only update fields that are present in data
      if (data.status) current.status = data.status
      if (data.started_at) current.started_at = data.started_at
      if (data.completed_at) current.completed_at = data.completed_at
      if (data.error_message !== undefined) current.error_message = data.error_message
      if (data.map_used) current.map_used = data.map_used
      if (data.plugins_wiped) current.plugins_wiped = data.plugins_wiped
      if (data.plugins_preserved) current.plugins_preserved = data.plugins_preserved
    } else {
      // Add new item if it doesn't exist (shouldn't happen, but defensive)
      fetchHistory().catch(console.error)
    }
  }

  // Subscribe to WebSocket events when store is initialized
  onMounted(() => {
    websocket.subscribe(handleWebSocketMessage)
  })

  async function fetchProfiles() {
    isLoading.value = true
    error.value = null
    try {
      const data = await api.get<WipeProfile[]>('/profiles')
      profiles.value = data
    } catch (err) {
      error.value = err instanceof Error ? err.message : 'Failed to fetch profiles'
      console.error('Failed to fetch wipe profiles:', err)
      throw err
    } finally {
      isLoading.value = false
    }
  }

  async function fetchSchedules() {
    isLoading.value = true
    error.value = null
    try {
      const data = await api.get<WipeSchedule[]>('/schedules')
      schedules.value = data
    } catch (err) {
      error.value = err instanceof Error ? err.message : 'Failed to fetch schedules'
      console.error('Failed to fetch wipe schedules:', err)
      throw err
    } finally {
      isLoading.value = false
    }
  }

  async function fetchHistory(limit = 50) {
    isLoading.value = true
    error.value = null
    try {
      const licenseId = authStore.license?.id
      if (!licenseId) {
        throw new Error('No license ID available')
      }

      const data = await api.get<WipeHistory[]>(`/wipes/history?limit=${limit}`)
      history.value = data
    } catch (err) {
      error.value = err instanceof Error ? err.message : 'Failed to fetch wipe history'
      console.error('Failed to fetch wipe history:', err)
      throw err
    } finally {
      isLoading.value = false
    }
  }

  async function triggerWipe(
    wipeType: 'map' | 'blueprint' | 'full',
    profileId: string
  ): Promise<{ wipe_history_id: string }> {
    isLoading.value = true
    error.value = null
    try {
      const licenseId = authStore.license?.id
      if (!licenseId) {
        throw new Error('No license ID available')
      }

      const result = await api.post<{ wipe_history_id: string }>(
        `/wipes/trigger`,
        {
          license_id: licenseId,
          wipe_type: wipeType,
          profile_id: profileId,
          trigger_type: 'manual',
        }
      )

      // Optimistically add pending wipe to history
      const newWipe: WipeHistory = {
        id: result.wipe_history_id,
        wipe_type: wipeType,
        trigger_type: 'manual',
        status: 'pending',
        started_at: null,
        completed_at: null,
        map_used: null,
        plugins_wiped: [],
        plugins_preserved: [],
        error_message: null,
      }
      history.value.unshift(newWipe)

      toast.success(`${wipeType.charAt(0).toUpperCase() + wipeType.slice(1)} wipe triggered successfully`)

      return result
    } catch (err) {
      error.value = err instanceof Error ? err.message : 'Failed to trigger wipe'
      console.error('Failed to trigger wipe:', err)
      throw err
    } finally {
      isLoading.value = false
    }
  }

  async function triggerDryRun(
    wipeType: 'map' | 'blueprint' | 'full',
    profileId: string
  ): Promise<{
    would_delete: string[]
    would_preserve: string[]
    estimated_duration_seconds: number
  }> {
    isLoading.value = true
    error.value = null
    try {
      const licenseId = authStore.license?.id
      if (!licenseId) {
        throw new Error('No license ID available')
      }

      const result = await api.post<{
        would_delete: string[]
        would_preserve: string[]
        estimated_duration_seconds: number
      }>(
        `/wipes/dry-run`,
        {
          license_id: licenseId,
          wipe_type: wipeType,
          profile_id: profileId,
        }
      )

      return result
    } catch (err) {
      error.value = err instanceof Error ? err.message : 'Failed to run dry-run'
      console.error('Failed to run dry-run:', err)
      throw err
    } finally {
      isLoading.value = false
    }
  }

  async function createProfile(profile: Omit<WipeProfile, 'id' | 'license_id'>): Promise<WipeProfile> {
    isLoading.value = true
    error.value = null
    try {
      const licenseId = authStore.license?.id
      if (!licenseId) {
        throw new Error('No license ID available')
      }

      const newProfile = await api.post<WipeProfile>('/profiles', {
        ...profile,
        license_id: licenseId,
      })

      profiles.value.push(newProfile)
      return newProfile
    } catch (err) {
      error.value = err instanceof Error ? err.message : 'Failed to create profile'
      console.error('Failed to create profile:', err)
      throw err
    } finally {
      isLoading.value = false
    }
  }

  async function updateProfile(id: string, updates: Partial<WipeProfile>): Promise<void> {
    isLoading.value = true
    error.value = null
    try {
      const updated = await api.put<WipeProfile>(`/profiles/${id}`, updates)
      const index = profiles.value.findIndex(p => p.id === id)
      if (index !== -1) {
        profiles.value[index] = updated
      }
    } catch (err) {
      error.value = err instanceof Error ? err.message : 'Failed to update profile'
      console.error('Failed to update profile:', err)
      throw err
    } finally {
      isLoading.value = false
    }
  }

  async function deleteProfile(id: string): Promise<void> {
    isLoading.value = true
    error.value = null
    try {
      await api.del(`/profiles/${id}`)
      profiles.value = profiles.value.filter(p => p.id !== id)
    } catch (err) {
      error.value = err instanceof Error ? err.message : 'Failed to delete profile'
      console.error('Failed to delete profile:', err)
      throw err
    } finally {
      isLoading.value = false
    }
  }

  return {
    profiles,
    schedules,
    history,
    isLoading,
    error,
    fetchProfiles,
    fetchSchedules,
    fetchHistory,
    triggerWipe,
    triggerDryRun,
    createProfile,
    updateProfile,
    deleteProfile,
  }
})
