import { defineStore } from 'pinia'
import { ref } from 'vue'
import type { Item } from '@/types/item'
import { apiClient, API_ENDPOINTS } from '@/services/api'
import { useSocket } from '@/composables/useSocket'
import { useNotificationStore } from '@/stores/notifications'
import { useAuthStore } from '@/stores/auth'

interface CreateItemPayload {
    listId: number
    data: {
        name: string
        quantity?: string | number | null
        category_id?: number | null
    }
}

interface UpdateItemPayload {
    listId: number
    itemId: number
    data: Partial<
        Omit<
            Item,
            | 'id'
            | 'list_id'
            | 'added_by_id'
            | 'completed_by_id'
            | 'added_by_user'
            | 'completed_by_user'
            | 'created_at'
            | 'updated_at'
        > & { version: number }
    >
}

export const useItemStore = defineStore('items', () => {
    const itemsByList = ref<Record<number, Item[]>>({})
    const isLoading = ref(false)
    const error = ref<string | null>(null)

    // Real-time state
    const { isConnected, on, off, emit } = useSocket()
    const notificationStore = useNotificationStore()
    const authStore = useAuthStore()

    // ---- Real-time Event Handlers ----
    function setupWebSocketListeners() {
        on('item:created', handleItemCreated)
        on('item:updated', handleItemUpdated)
        on('item:deleted', handleItemDeleted)
        on('item:claimed', handleItemClaimed)
        on('item:unclaimed', handleItemUnclaimed)
    }

    function cleanupWebSocketListeners() {
        off('item:created', handleItemCreated)
        off('item:updated', handleItemUpdated)
        off('item:deleted', handleItemDeleted)
        off('item:claimed', handleItemClaimed)
        off('item:unclaimed', handleItemUnclaimed)
    }

    function handleItemCreated(payload: { item: Item }) {
        const { item } = payload
        const listId = item.list_id
        if (!itemsByList.value[listId]) {
            itemsByList.value[listId] = []
        }
        // Only add if not already present (prevent duplicates)
        if (!itemsByList.value[listId].find(i => i.id === item.id)) {
            itemsByList.value[listId].push(item)

            // Show notification if added by someone else
            if (item.added_by_id !== authStore.user?.id) {
                notificationStore.addNotification({
                    message: `"${item.name}" was added to the shopping list`,
                    type: 'info',
                    duration: 3000
                })
            }
        }
    }

    function handleItemUpdated(payload: { item: Item }) {
        const { item } = payload
        const listId = item.list_id
        const items = itemsByList.value[listId]
        if (items) {
            const index = items.findIndex(i => i.id === item.id)
            if (index >= 0) {
                items[index] = item
            }
        }
    }

    function handleItemDeleted(payload: { itemId: number, listId: number }) {
        const { itemId, listId } = payload
        const items = itemsByList.value[listId]
        if (items) {
            itemsByList.value[listId] = items.filter(i => i.id !== itemId)
        }
    }

    function handleItemClaimed(payload: { item: Item }) {
        // Same as update - claiming updates the item
        handleItemUpdated(payload)

        // Show notification if claimed by someone else
        if (payload.item.claimed_by_user_id !== authStore.user?.id) {
            notificationStore.addNotification({
                message: `"${payload.item.name}" was claimed for shopping`,
                type: 'info',
                duration: 3000
            })
        }
    }

    function handleItemUnclaimed(payload: { item: Item }) {
        // Same as update - unclaiming updates the item
        handleItemUpdated(payload)

        // Show notification if unclaimed by someone else
        notificationStore.addNotification({
            message: `"${payload.item.name}" is available for shopping again`,
            type: 'info',
            duration: 3000
        })
    }

    function setError(message: string) {
        error.value = message
        isLoading.value = false
    }

    async function fetchItems(listId: number) {
        isLoading.value = true
        error.value = null
        try {
            const endpoint = API_ENDPOINTS.LISTS.ITEMS(String(listId))
            const { data } = await apiClient.get(endpoint)
            itemsByList.value[listId] = data as Item[]
        } catch (e: any) {
            setError(e?.response?.data?.detail || e.message || 'Failed to load items')
        } finally {
            isLoading.value = false
        }
    }

    async function addItem(payload: CreateItemPayload) {
        const { listId, data } = payload
        try {
            const endpoint = API_ENDPOINTS.LISTS.ITEMS(String(listId))
            const { data: created } = await apiClient.post(endpoint, data)
            if (!itemsByList.value[listId]) itemsByList.value[listId] = []
            itemsByList.value[listId].push(created as Item)

            // Emit real-time event
            emit('item:created', { item: created })
            return created as Item
        } catch (e: any) {
            setError(e?.response?.data?.detail || e.message || 'Failed to add item')
            throw e
        }
    }

    async function updateItem(payload: UpdateItemPayload) {
        const { listId, itemId, data } = payload
        try {
            const endpoint = API_ENDPOINTS.LISTS.ITEM(String(listId), String(itemId))
            const { data: updated } = await apiClient.put(endpoint, data)
            const arr = itemsByList.value[listId]
            if (arr) {
                const idx = arr.findIndex((it) => it.id === itemId)
                if (idx !== -1) arr[idx] = updated as Item
            }

            // Emit real-time event
            emit('item:updated', { item: updated })
            return updated as Item
        } catch (e: any) {
            setError(e?.response?.data?.detail || e.message || 'Failed to update item')
            throw e
        }
    }

    async function deleteItem(listId: number, itemId: number, expectedVersion?: number) {
        try {
            const endpoint = API_ENDPOINTS.LISTS.ITEM(String(listId), String(itemId))
            const config = expectedVersion ? { params: { expected_version: expectedVersion } } : {}
            await apiClient.delete(endpoint, config)
            const arr = itemsByList.value[listId]
            if (arr) itemsByList.value[listId] = arr.filter((it) => it.id !== itemId)

            // Emit real-time event
            emit('item:deleted', { itemId, listId })
        } catch (e: any) {
            setError(e?.response?.data?.detail || e.message || 'Failed to delete item')
            throw e
        }
    }

    // Initialize WebSocket listeners
    setupWebSocketListeners()

    return {
        itemsByList,
        isLoading,
        error,
        fetchItems,
        addItem,
        updateItem,
        deleteItem,
        setError,

        // Real-time
        isConnected,
        setupWebSocketListeners,
        cleanupWebSocketListeners,
    }
}) 