import { create } from 'zustand'
import type { PbiStatusApi } from '@/lib/task-status'

export interface BacklogPbi {
  id: string
  code: string | null
  title: string
  priority: number
  description?: string | null
  created_at: Date
  status: PbiStatusApi
}

export interface BacklogStory {
  id: string
  code: string | null
  title: string
  description: string | null
  acceptance_criteria: string | null
  priority: number
  status: string
  pbi_id: string
  created_at: Date
}

export interface BacklogTask {
  id: string
  title: string
  description: string | null
  priority: number
  status: string
  sort_order: number
  story_id: string
  created_at: Date
}

type Entity = 'pbi' | 'story' | 'task'
type Op = 'I' | 'U' | 'D'

interface InitialData {
  pbis: BacklogPbi[]
  storiesByPbi: Record<string, BacklogStory[]>
  tasksByStory: Record<string, BacklogTask[]>
}

interface BacklogStore extends InitialData {
  setInitialData: (data: InitialData) => void
  applyChange: (entity: Entity, op: Op, data: Record<string, unknown>) => void
}

export const useBacklogStore = create<BacklogStore>((set) => ({
  pbis: [],
  storiesByPbi: {},
  tasksByStory: {},

  setInitialData: (data) => set(data),

  applyChange: (entity, op, data) =>
    set((state) => {
      if (entity === 'pbi') {
        const id = data.id as string
        if (op === 'D') {
          return { pbis: state.pbis.filter((p) => p.id !== id) }
        }
        if (op === 'U') {
          return {
            pbis: state.pbis.map((p) =>
              p.id === id ? { ...p, ...(data as Partial<BacklogPbi>) } : p
            ),
          }
        }
        // I — idempotent: skip if already present (optimistic update may have arrived first)
        if (state.pbis.some((p) => p.id === id)) return {}
        return { pbis: [...state.pbis, data as unknown as BacklogPbi] }
      }

      if (entity === 'story') {
        const id = data.id as string
        if (op === 'D') {
          const storiesByPbi = { ...state.storiesByPbi }
          for (const pbiId of Object.keys(storiesByPbi)) {
            storiesByPbi[pbiId] = storiesByPbi[pbiId].filter((s) => s.id !== id)
          }
          return { storiesByPbi }
        }
        if (op === 'U') {
          const storiesByPbi = { ...state.storiesByPbi }
          for (const pbiId of Object.keys(storiesByPbi)) {
            const idx = storiesByPbi[pbiId].findIndex((s) => s.id === id)
            if (idx !== -1) {
              storiesByPbi[pbiId] = storiesByPbi[pbiId].map((s) =>
                s.id === id ? { ...s, ...(data as Partial<BacklogStory>) } : s
              )
              break
            }
          }
          return { storiesByPbi }
        }
        // I — idempotent: skip if already present
        const pbiId = data.pbi_id as string
        if ((state.storiesByPbi[pbiId] ?? []).some((s) => s.id === id)) return {}
        return {
          storiesByPbi: {
            ...state.storiesByPbi,
            [pbiId]: [...(state.storiesByPbi[pbiId] ?? []), data as unknown as BacklogStory],
          },
        }
      }

      // task
      const id = data.id as string
      if (op === 'D') {
        const tasksByStory = { ...state.tasksByStory }
        for (const storyId of Object.keys(tasksByStory)) {
          tasksByStory[storyId] = tasksByStory[storyId].filter((t) => t.id !== id)
        }
        return { tasksByStory }
      }
      if (op === 'U') {
        const tasksByStory = { ...state.tasksByStory }
        for (const storyId of Object.keys(tasksByStory)) {
          const idx = tasksByStory[storyId].findIndex((t) => t.id === id)
          if (idx !== -1) {
            tasksByStory[storyId] = tasksByStory[storyId].map((t) =>
              t.id === id ? { ...t, ...(data as Partial<BacklogTask>) } : t
            )
            break
          }
        }
        return { tasksByStory }
      }
      // I — idempotent: skip if already present
      const storyId = data.story_id as string
      if ((state.tasksByStory[storyId] ?? []).some((t) => t.id === id)) return {}
      return {
        tasksByStory: {
          ...state.tasksByStory,
          [storyId]: [...(state.tasksByStory[storyId] ?? []), data as unknown as BacklogTask],
        },
      }
    }),
}))
