// src/stores/offline.ts (Example modification)
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
// import { LocalStorage } from 'quasar'; // REMOVE
import { useStorage } from '@vueuse/core' // VueUse alternative
import { useNotificationStore } from '@/stores/notifications' // Your custom notification store
import { api } from '@/services/api'
import { API_ENDPOINTS } from '@/config/api-config'

export type CreateListPayload = { name: string; description?: string /* other list properties */ }
export type UpdateListPayload = {
  listId: string
  data: Partial<CreateListPayload>
  version?: number
}
export type DeleteListPayload = { listId: string }
export type CreateListItemPayload = {
  listId: string
  itemData: {
    name: string
    quantity?: number | string
    completed?: boolean
    price?: number | null
    category_id?: number | null
  }
}
export type UpdateListItemPayload = {
  listId: string
  itemId: string
  data: Partial<CreateListItemPayload['itemData']>
  version?: number
}
export type DeleteListItemPayload = { listId: string; itemId: string }

export type OfflineAction = {
  id: string
  timestamp: number
  type:
  | 'create_list'
  | 'update_list'
  | 'delete_list'
  | 'create_list_item'
  | 'update_list_item'
  | 'delete_list_item'
  payload:
  | CreateListPayload
  | UpdateListPayload
  | DeleteListPayload
  | CreateListItemPayload
  | UpdateListItemPayload
  | DeleteListItemPayload
}

export type ConflictData = {
  localVersion: { data: Record<string, unknown>; timestamp: number }
  serverVersion: { data: Record<string, unknown>; timestamp: number }
  action: OfflineAction
}

interface ServerListData {
  id: string
  version: number
  name: string
  [key: string]: unknown
}

interface ServerItemData {
  id: string
  version: number
  name: string
  [key: string]: unknown
}

export const useOfflineStore = defineStore('offline', () => {
  // const $q = useQuasar(); // REMOVE
  const notificationStore = useNotificationStore()
  const isOnline = ref(navigator.onLine)

  // Use useStorage for reactive localStorage
  const pendingActions = useStorage<OfflineAction[]>('offline-actions', [])

  const isProcessingQueue = ref(false)
  const showConflictDialog = ref(false) // You'll need to implement this dialog
  const currentConflict = ref<ConflictData | null>(null)

  // init is now handled by useStorage automatically loading the value

  // saveToStorage is also handled by useStorage automatically saving on change

  const addAction = (action: Omit<OfflineAction, 'id' | 'timestamp'>) => {
    const newAction = {
      ...action,
      id: crypto.randomUUID(),
      timestamp: Date.now(),
    } as OfflineAction
    pendingActions.value.push(newAction)
  }

  const processQueue = async () => {
    if (isProcessingQueue.value || !isOnline.value) return
    isProcessingQueue.value = true
    const actionsToProcess = [...pendingActions.value] // Create a copy to iterate

    for (const action of actionsToProcess) {
      try {
        await processAction(action)
        pendingActions.value = pendingActions.value.filter((a) => a.id !== action.id)
      } catch (error: any) {
        // Catch error as any to check for our custom flag
        if (error && error.isConflict && error.serverVersionData) {
          notificationStore.addNotification({
            type: 'warning',
            message: `Conflict detected for action ${action.type}. Please review.`,
          })

          let localData: Record<string, unknown>
          // Extract local data based on action type
          if (action.type === 'update_list' || action.type === 'update_list_item') {
            localData = (action.payload as UpdateListPayload | UpdateListItemPayload).data
          } else if (action.type === 'create_list' || action.type === 'create_list_item') {
            localData = action.payload as CreateListPayload | CreateListItemPayload
          } else {
            console.error(
              'Conflict detected for unhandled action type for data extraction:',
              action.type,
            )
            localData = {} // Fallback
          }

          currentConflict.value = {
            localVersion: {
              data: localData,
              timestamp: action.timestamp,
            },
            serverVersion: {
              data: error.serverVersionData, // Assumes API 409 response body is the server item
              timestamp: error.serverVersionData.updated_at
                ? new Date(error.serverVersionData.updated_at).getTime()
                : action.timestamp + 1, // Prefer server updated_at
            },
            action: action,
          }
          showConflictDialog.value = true
          console.warn('Conflict detected by processQueue for action:', action.id, error)
          // Stop processing queue on first conflict to await resolution
          isProcessingQueue.value = false // Allow queue to be re-triggered after resolution
          return // Stop processing further actions
        } else {
          console.error('processQueue: Action failed, remains in queue:', action.id, error)
        }
      }
    }
    isProcessingQueue.value = false
  }

  const processAction = async (action: OfflineAction) => {
    try {
      let request: Request
      let endpoint: string
      let method: 'POST' | 'PUT' | 'DELETE' = 'POST'
      let body: any

      switch (action.type) {
        case 'create_list':
          endpoint = API_ENDPOINTS.LISTS.BASE
          body = action.payload
          break
        case 'update_list': {
          const { listId, data } = action.payload as UpdateListPayload
          endpoint = API_ENDPOINTS.LISTS.BY_ID(listId)
          method = 'PUT'
          body = data
          break
        }
        case 'delete_list': {
          const { listId } = action.payload as DeleteListPayload
          endpoint = API_ENDPOINTS.LISTS.BY_ID(listId)
          method = 'DELETE'
          break
        }
        case 'create_list_item': {
          const { listId, itemData } = action.payload as CreateListItemPayload
          endpoint = API_ENDPOINTS.LISTS.ITEMS(listId)
          body = itemData
          break
        }
        case 'update_list_item': {
          const { listId, itemId, data } = action.payload as UpdateListItemPayload
          endpoint = API_ENDPOINTS.LISTS.ITEM(listId, itemId)
          method = 'PUT'
          body = data
          break
        }
        case 'delete_list_item': {
          const { listId, itemId } = action.payload as DeleteListItemPayload
          endpoint = API_ENDPOINTS.LISTS.ITEM(listId, itemId)
          method = 'DELETE'
          break
        }
        default:
          throw new Error(`Unknown action type: ${action.type}`)
      }

      // Create the request with the action metadata
      request = new Request(endpoint, {
        method,
        headers: {
          'Content-Type': 'application/json',
          'X-Offline-Action': action.id,
        },
        body: method !== 'DELETE' ? JSON.stringify(body) : undefined,
      })

      // Use fetch with the request
      const response = await fetch(request)

      if (!response.ok) {
        if (response.status === 409) {
          const error = new Error('Conflict detected') as any
          error.isConflict = true
          error.serverVersionData = await response.json()
          throw error
        }
        throw new Error(`HTTP error! status: ${response.status}`)
      }

      // If successful, remove from pending actions
      pendingActions.value = pendingActions.value.filter((a) => a.id !== action.id)
      return await response.json()
    } catch (error: any) {
      if (error.isConflict) {
        throw error
      }
      // For other errors, let Workbox handle the retry
      throw error
    }
  }

  const setupNetworkListeners = () => {
    window.addEventListener('online', () => {
      isOnline.value = true
      processQueue().catch((err) => console.error('Error processing queue on online event:', err))
    })
    window.addEventListener('offline', () => {
      isOnline.value = false
    })
  }

  setupNetworkListeners() // Call this once

  const hasPendingActions = computed(() => pendingActions.value.length > 0)
  const pendingActionCount = computed(() => pendingActions.value.length)

  const handleConflictResolution = async (resolution: {
    version: 'local' | 'server' | 'merge'
    action: OfflineAction
    mergedData?: Record<string, unknown>
  }) => {
    if (!resolution.action || !currentConflict.value) {
      console.error('handleConflictResolution called without an action or active conflict.')
      showConflictDialog.value = false
      currentConflict.value = null
      return
    }
    const { action, version, mergedData } = resolution
    const serverVersionNumber = (currentConflict.value.serverVersion.data as any)?.version

    try {
      let success = false
      if (version === 'local') {
        let dataToPush: any
        let endpoint: string
        let method: 'post' | 'put' = 'put'

        if (action.type === 'update_list') {
          const payload = action.payload as UpdateListPayload
          dataToPush = { ...payload.data, version: serverVersionNumber }
          endpoint = API_ENDPOINTS.LISTS.BY_ID(payload.listId)
        } else if (action.type === 'update_list_item') {
          const payload = action.payload as UpdateListItemPayload
          dataToPush = { ...payload.data, version: serverVersionNumber }
          endpoint = API_ENDPOINTS.LISTS.ITEM(payload.listId, payload.itemId)
        } else if (action.type === 'create_list') {
          const serverData = currentConflict.value.serverVersion.data as ServerListData | null
          if (serverData?.id) {
            // Server returned existing list, update it instead
            dataToPush = { ...action.payload, version: serverData.version }
            endpoint = API_ENDPOINTS.LISTS.BY_ID(serverData.id)
          } else {
            // True conflict, need to modify the data
            dataToPush = {
              ...action.payload,
              name: `${(action.payload as CreateListPayload).name} (${new Date().toLocaleString()})`,
            }
            endpoint = API_ENDPOINTS.LISTS.BASE
            method = 'post'
          }
        } else if (action.type === 'create_list_item') {
          const serverData = currentConflict.value.serverVersion.data as ServerItemData | null
          if (serverData?.id) {
            // Server returned existing item, update it instead
            dataToPush = { ...action.payload, version: serverData.version }
            endpoint = API_ENDPOINTS.LISTS.ITEM(
              (action.payload as CreateListItemPayload).listId,
              serverData.id,
            )
          } else {
            // True conflict, need to modify the data
            dataToPush = {
              ...action.payload,
              name: `${(action.payload as CreateListItemPayload).itemData.name} (${new Date().toLocaleString()})`,
            }
            endpoint = API_ENDPOINTS.LISTS.ITEMS((action.payload as CreateListItemPayload).listId)
            method = 'post'
          }
        } else {
          console.error("Unsupported action type for 'keep local' resolution:", action.type)
          throw new Error("Unsupported action for 'keep local'")
        }

        if (method === 'put') {
          await api.put(endpoint, dataToPush)
        } else {
          await api.post(endpoint, dataToPush)
        }
        success = true
        notificationStore.addNotification({
          type: 'success',
          message: 'Your version was saved to the server.',
        })
      } else if (version === 'server') {
        success = true
        notificationStore.addNotification({
          type: 'info',
          message: 'Local changes discarded; server version kept.',
        })
      } else if (version === 'merge' && mergedData) {
        let dataWithVersion: any
        let endpoint: string

        if (action.type === 'update_list') {
          const payload = action.payload as UpdateListPayload
          dataWithVersion = { ...mergedData, version: serverVersionNumber }
          endpoint = API_ENDPOINTS.LISTS.BY_ID(payload.listId)
        } else if (action.type === 'update_list_item') {
          const payload = action.payload as UpdateListItemPayload
          dataWithVersion = { ...mergedData, version: serverVersionNumber }
          endpoint = API_ENDPOINTS.LISTS.ITEM(payload.listId, payload.itemId)
        } else if (action.type === 'create_list' || action.type === 'create_list_item') {
          // For create actions, merging means updating the existing item
          const serverData = currentConflict.value.serverVersion.data as
            | (ServerListData | ServerItemData)
            | null
          if (!serverData?.id) {
            throw new Error('Cannot merge create action: server data is missing or invalid')
          }

          if (action.type === 'create_list') {
            dataWithVersion = { ...mergedData, version: serverData.version }
            endpoint = API_ENDPOINTS.LISTS.BY_ID(serverData.id)
          } else {
            dataWithVersion = { ...mergedData, version: serverData.version }
            endpoint = API_ENDPOINTS.LISTS.ITEM(
              (action.payload as CreateListItemPayload).listId,
              serverData.id,
            )
          }
        } else {
          console.error('Merge resolution for unsupported action type:', action.type)
          throw new Error('Merge for this action type is not supported')
        }

        await api.put(endpoint, dataWithVersion)
        success = true
        notificationStore.addNotification({
          type: 'success',
          message: 'Merged version saved to the server.',
        })
      }

      if (success) {
        pendingActions.value = pendingActions.value.filter((a) => a.id !== action.id)
      }
    } catch (error) {
      console.error('Error during conflict resolution API call:', error)
      notificationStore.addNotification({
        type: 'error',
        message: `Failed to resolve conflict for ${action.type}. Please try again.`,
      })
    } finally {
      showConflictDialog.value = false
      currentConflict.value = null
      processQueue().catch((err) =>
        console.error('Error processing queue after conflict resolution:', err),
      )
    }
  }

  return {
    isOnline,
    pendingActions,
    isProcessingQueue,
    showConflictDialog,
    currentConflict,
    addAction,
    processAction,
    processQueue,
    handleConflictResolution,
    hasPendingActions,
    pendingActionCount,
  }
})
