import { create } from 'zustand'
import { pinnedFlowsApi } from '@/api/pinnedFlows'
import type { PinnedFlow } from '@/api/pinnedFlows'
import { toast } from '@/lib/toast'

interface PinnedFlowsState {
  items: PinnedFlow[]
  isLoaded: boolean
  isLoading: boolean
  isMutatingByTreeId: Record<string, boolean>
  error: string | null

  load: (force?: boolean) => Promise<void>
  pin: (treeId: string) => Promise<void>
  unpin: (treeId: string) => Promise<void>
  toggle: (treeId: string) => void
  isPinned: (treeId: string) => boolean
}

export const usePinnedFlowsStore = create<PinnedFlowsState>()((set, get) => ({
  items: [],
  isLoaded: false,
  isLoading: false,
  isMutatingByTreeId: {},
  error: null,

  load: async (force = false) => {
    const state = get()
    if (state.isLoaded && !force) return
    if (state.isLoading) return

    set({ isLoading: true, error: null })
    try {
      const data = await pinnedFlowsApi.list()
      set({ items: data.items, isLoaded: true, isLoading: false })
    } catch {
      set({ error: 'Failed to load pinned flows', isLoading: false })
    }
  },

  pin: async (treeId: string) => {
    const state = get()
    if (state.isMutatingByTreeId[treeId]) return

    set({ isMutatingByTreeId: { ...state.isMutatingByTreeId, [treeId]: true } })

    try {
      await pinnedFlowsApi.pin(treeId)
      const data = await pinnedFlowsApi.list()
      set((s) => ({
        items: data.items,
        isMutatingByTreeId: { ...s.isMutatingByTreeId, [treeId]: false },
      }))
    } catch (err: unknown) {
      const status = (err as { response?: { status?: number } })?.response?.status
      if (status === 409) {
        toast.error('Maximum of 15 favorites reached. Unpin a flow to add a new one.')
      } else {
        toast.error('Failed to pin flow')
      }
      set((s) => ({
        isMutatingByTreeId: { ...s.isMutatingByTreeId, [treeId]: false },
      }))
    }
  },

  unpin: async (treeId: string) => {
    const state = get()
    if (state.isMutatingByTreeId[treeId]) return

    const prevItems = state.items
    set({
      items: state.items.filter((f) => f.tree_id !== treeId),
      isMutatingByTreeId: { ...state.isMutatingByTreeId, [treeId]: true },
    })

    try {
      await pinnedFlowsApi.unpin(treeId)
      set((s) => ({
        isMutatingByTreeId: { ...s.isMutatingByTreeId, [treeId]: false },
      }))
    } catch {
      toast.error('Failed to unpin flow')
      set((s) => ({
        items: prevItems,
        isMutatingByTreeId: { ...s.isMutatingByTreeId, [treeId]: false },
      }))
    }
  },

  toggle: (treeId: string) => {
    const state = get()
    if (state.isPinned(treeId)) {
      state.unpin(treeId)
    } else {
      state.pin(treeId)
    }
  },

  isPinned: (treeId: string) => {
    return get().items.some((f) => f.tree_id === treeId)
  },
}))

