'use client'

import { useState, useEffect, useTransition } from 'react'
import {
  DndContext, DragEndEvent,
  KeyboardSensor, PointerSensor, useSensor, useSensors, closestCenter,
} from '@dnd-kit/core'
import { sortableKeyboardCoordinates, arrayMove } from '@dnd-kit/sortable'
import { toast } from 'sonner'
import { SplitPane } from '@/components/split-pane/split-pane'
import { SprintBacklogLeft, SprintBacklogRight } from './sprint-backlog'
import type { SprintStory, PbiWithStories } from './sprint-backlog'
import { useSprintStore } from '@/stores/sprint-store'
import {
  addStoryToSprintAction,
  removeStoryFromSprintAction,
  reorderSprintStoriesAction,
} from '@/actions/sprints'

interface SprintBacklogClientProps {
  productId: string
  sprintId: string
  stories: SprintStory[]
  pbisWithStories: PbiWithStories[]
  sprintStoryIdList: string[]
  isDemo: boolean
}

export function SprintBacklogClient({
  productId,
  sprintId,
  stories,
  pbisWithStories,
  sprintStoryIdList,
  isDemo,
}: SprintBacklogClientProps) {
  const [sprintStories, setSprintStories] = useState<SprintStory[]>(stories)
  const [sprintStoryIds, setSprintStoryIds] = useState<Set<string>>(() => new Set(sprintStoryIdList))
  const {
    sprintStoryOrder,
    initSprint,
    addStoryToSprint,
    removeStoryFromSprint,
    reorderSprintStories,
    rollbackSprint,
  } = useSprintStore()
  const [, startTransition] = useTransition()

  useEffect(() => {
    initSprint(sprintId, stories.map(s => s.id))
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [sprintId])

  const sensors = useSensors(
    useSensor(PointerSensor, { activationConstraint: { distance: 5 } }),
    useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })
  )

  function handleDragEnd(event: DragEndEvent) {
    const { active, over } = event
    if (!over) return

    const activeId = active.id.toString()
    const overId = over.id.toString()
    const order = sprintStoryOrder[sprintId] ?? sprintStories.map(s => s.id)

    // Dragged from right panel (pb: prefix) → add to sprint
    if (activeId.startsWith('pb:')) {
      const storyId = activeId.slice(3)
      const droppingOnSprint =
        overId === 'sprint-zone' ||
        (!overId.startsWith('pb:') && overId !== 'backlog-zone')
      if (droppingOnSprint && !sprintStoryIds.has(storyId)) {
        const storyData = pbisWithStories.flatMap(p => p.stories).find(s => s.id === storyId)
        if (!storyData) return
        setSprintStoryIds(prev => new Set([...prev, storyId]))
        setSprintStories(prev => [...prev, storyData])
        addStoryToSprint(sprintId, storyId)
        startTransition(async () => {
          const result = await addStoryToSprintAction(sprintId, storyId)
          if (!result.success) {
            setSprintStoryIds(prev => { const n = new Set(prev); n.delete(storyId); return n })
            setSprintStories(prev => prev.filter(s => s.id !== storyId))
            removeStoryFromSprint(sprintId, storyId)
            toast.error(result.error ?? 'Toevoegen mislukt')
          }
        })
      }
      return
    }

    // Dragged from left panel to right panel → remove from sprint
    if (overId === 'backlog-zone') {
      const storyData = sprintStories.find(s => s.id === activeId)
      setSprintStoryIds(prev => { const n = new Set(prev); n.delete(activeId); return n })
      setSprintStories(prev => prev.filter(s => s.id !== activeId))
      removeStoryFromSprint(sprintId, activeId)
      startTransition(async () => {
        const result = await removeStoryFromSprintAction(activeId)
        if (!result.success) {
          if (storyData) {
            setSprintStoryIds(prev => new Set([...prev, activeId]))
            setSprintStories(prev => [...prev, storyData])
          }
          addStoryToSprint(sprintId, activeId)
          toast.error('Verwijderen mislukt')
        }
      })
      return
    }

    // Reorder within sprint
    if (activeId !== overId && order.includes(overId)) {
      const prevOrder = [...order]
      const newOrder = arrayMove([...order], order.indexOf(activeId), order.indexOf(overId))
      reorderSprintStories(sprintId, newOrder)
      startTransition(async () => {
        const result = await reorderSprintStoriesAction(sprintId, newOrder)
        if (!result.success) {
          rollbackSprint(sprintId, prevOrder)
          toast.error('Volgorde opslaan mislukt')
        }
      })
    }
  }

  function handleRemove(storyId: string) {
    const storyData = sprintStories.find(s => s.id === storyId)
    setSprintStoryIds(prev => { const n = new Set(prev); n.delete(storyId); return n })
    setSprintStories(prev => prev.filter(s => s.id !== storyId))
    removeStoryFromSprint(sprintId, storyId)
    startTransition(async () => {
      const result = await removeStoryFromSprintAction(storyId)
      if (!result.success) {
        if (storyData) {
          setSprintStoryIds(prev => new Set([...prev, storyId]))
          setSprintStories(prev => [...prev, storyData])
        }
        addStoryToSprint(sprintId, storyId)
        toast.error('Verwijderen mislukt')
      }
    })
  }

  return (
    <DndContext sensors={sensors} collisionDetection={closestCenter} onDragEnd={handleDragEnd}>
      <SplitPane
        storageKey={`sprint-${productId}`}
        left={
          <SprintBacklogLeft
            sprintId={sprintId}
            stories={sprintStories}
            isDemo={isDemo}
            onRemove={handleRemove}
          />
        }
        right={
          <SprintBacklogRight
            pbisWithStories={pbisWithStories}
            sprintStoryIds={sprintStoryIds}
            isDemo={isDemo}
          />
        }
      />
    </DndContext>
  )
}
