'use client'

import { useState, useTransition, useEffect, useActionState } from 'react'
import { useFormStatus } from 'react-dom'
import {
  DndContext, DragEndEvent, DragOverlay,
  KeyboardSensor, PointerSensor, useSensor, useSensors, closestCenter,
} from '@dnd-kit/core'
import {
  SortableContext, useSortable, verticalListSortingStrategy, arrayMove,
  sortableKeyboardCoordinates,
} from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
import { toast } from 'sonner'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Badge } from '@/components/ui/badge'
import { CodeBadge } from '@/components/shared/code-badge'
import { PanelNavBar } from '@/components/shared/panel-nav-bar'
import { PRIORITY_BORDER } from '@/components/backlog/backlog-card'
import { deriveTaskCode } from '@/lib/code'
import { useSprintStore } from '@/stores/sprint-store'
import {
  createTaskAction, updateTaskStatusAction, updateTaskAction,
  deleteTaskAction, reorderTasksAction,
} from '@/actions/tasks'
import { cn } from '@/lib/utils'

const STATUS_CYCLE: Record<string, 'TO_DO' | 'IN_PROGRESS' | 'DONE'> = {
  TO_DO: 'IN_PROGRESS',
  IN_PROGRESS: 'DONE',
  DONE: 'TO_DO',
}
const STATUS_COLORS: Record<string, string> = {
  TO_DO: 'bg-status-todo/15 text-status-todo border-status-todo/30',
  IN_PROGRESS: 'bg-status-in-progress/15 text-status-in-progress border-status-in-progress/30',
  DONE: 'bg-status-done/15 text-status-done border-status-done/30',
}
const STATUS_LABELS: Record<string, string> = { TO_DO: 'To Do', IN_PROGRESS: 'Bezig', DONE: 'Klaar' }


export interface Task {
  id: string
  title: string
  description: string | null
  priority: number
  status: string
  story_id: string
  sprint_id: string | null
}

interface TaskListProps {
  storyId: string
  storyCode: string | null
  sprintId: string
  productId: string
  tasks: Task[]
  isDemo: boolean
}

function SortableTaskRow({
  task, code, isDemo, onStatusToggle, onDelete,
}: { task: Task; code: string | null; isDemo: boolean; onStatusToggle: () => void; onDelete: () => void }) {
  const [editing, setEditing] = useState(false)
  const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ id: task.id })
  const style = { transform: CSS.Transform.toString(transform), transition, opacity: isDragging ? 0.4 : 1 }

  const [, formAction] = useActionState(
    async (_prev: unknown, fd: FormData) => {
      const result = await updateTaskAction(_prev, fd)
      if (result?.success) setEditing(false)
      return result
    },
    undefined
  )

  if (editing) {
    return (
      <div ref={setNodeRef} style={style} className="px-2 py-1">
        <div className={cn('rounded border border-border px-3 py-2 bg-surface-container', PRIORITY_BORDER[task.priority])}>
          <form action={formAction} className="space-y-2">
            <input type="hidden" name="id" value={task.id} />
            <input type="hidden" name="priority" value={task.priority} />
            <Input name="title" defaultValue={task.title} className="h-7 text-sm" required autoFocus />
            <div className="flex gap-2">
              <EditSubmitButton />
              <Button type="button" variant="ghost" size="sm" className="h-7" onClick={() => setEditing(false)}>Annuleren</Button>
            </div>
          </form>
        </div>
      </div>
    )
  }

  return (
    <div ref={setNodeRef} style={style} className="group px-2 py-1">
      <div className={cn(
        'flex items-start gap-2 rounded border border-border px-3 py-2 transition-colors bg-surface-container hover:bg-surface-container-high',
        PRIORITY_BORDER[task.priority]
      )}>
        {!isDemo && (
          <span {...attributes} {...listeners} className="text-muted-foreground cursor-grab active:cursor-grabbing shrink-0 text-sm select-none mt-0.5">⠿</span>
        )}
        <div className="flex-1 min-w-0">
          <div className="flex items-start justify-between gap-2">
            <p className={cn('text-sm leading-snug line-clamp-2 flex-1', task.status === 'DONE' && 'line-through text-muted-foreground')}>
              {task.title}
            </p>
            {code && <CodeBadge code={code} className="shrink-0 mt-0.5" />}
          </div>
          <div className="flex items-center justify-between gap-2 mt-1.5">
            <button onClick={onStatusToggle} disabled={isDemo} aria-label={`Status: ${STATUS_LABELS[task.status]}`}>
              <Badge className={cn('text-[10px] px-1.5 py-0 border cursor-pointer hover:opacity-80 transition-opacity', STATUS_COLORS[task.status])}>
                {STATUS_LABELS[task.status]}
              </Badge>
            </button>
            {!isDemo && (
              <div className="opacity-0 group-hover:opacity-100 flex gap-1 shrink-0">
                <button onClick={() => setEditing(true)} className="text-xs text-muted-foreground hover:text-foreground">Bewerk</button>
                <button onClick={onDelete} aria-label="Verwijder taak" className="text-xs text-muted-foreground hover:text-error">×</button>
              </div>
            )}
          </div>
        </div>
      </div>
    </div>
  )
}

function EditSubmitButton() {
  const { pending } = useFormStatus()
  return <Button type="submit" size="sm" className="h-7" disabled={pending}>{pending ? '…' : 'Opslaan'}</Button>
}

function CreateTaskForm({ storyId, sprintId, onDone }: { storyId: string; sprintId: string; onDone: () => void }) {
  const [state, formAction] = useActionState(
    async (_prev: unknown, fd: FormData) => {
      const result = await createTaskAction(_prev, fd)
      if (result?.success) { onDone(); return result }
      if (result?.error) toast.error(typeof result.error === 'string' ? result.error : 'Aanmaken mislukt')
      return result
    },
    undefined
  )
  return (
    <form action={formAction} className="flex flex-col gap-1.5 px-4 py-2 border-b border-border">
      <input type="hidden" name="storyId" value={storyId} />
      <input type="hidden" name="sprintId" value={sprintId} />
      <input type="hidden" name="priority" value="2" />
      <div className="flex gap-2">
        <Input name="title" autoFocus placeholder="Taaknaam…" className="h-7 text-sm flex-1" required />
        <CreateSubmitButton />
        <Button type="button" variant="ghost" size="sm" className="h-7" aria-label="Annuleer" onClick={onDone}>×</Button>
      </div>
      {state && 'error' in state && typeof state.error === 'string' && (
        <p className="text-xs text-destructive">{state.error}</p>
      )}
    </form>
  )
}

function CreateSubmitButton() {
  const { pending } = useFormStatus()
  return <Button type="submit" size="sm" className="h-7" disabled={pending}>{pending ? '…' : 'Toevoegen'}</Button>
}

export function TaskList({ storyId, storyCode, sprintId, productId: _productId, tasks, isDemo }: TaskListProps) {
  const { taskOrder, initTasks, reorderTasks, rollbackTasks } = useSprintStore()
  const [creating, setCreating] = useState(false)
  const [activeDragId, setActiveDragId] = useState<string | null>(null)
  const [, startTransition] = useTransition()

  const idKey = tasks.map(t => t.id).join(',')
  useEffect(() => {
    initTasks(storyId, idKey ? idKey.split(',') : [])
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [storyId, idKey])

  const taskMap = Object.fromEntries(tasks.map(t => [t.id, t]))
  const order = taskOrder[storyId] ?? tasks.map(t => t.id)
  const orderedTasks = order.map(id => taskMap[id]).filter(Boolean)

  const doneCount = orderedTasks.filter(t => t.status === 'DONE').length

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

  function handleDragEnd(event: DragEndEvent) {
    const { active, over } = event
    if (!over || active.id === over.id) return
    const prevOrder = [...order]
    const newOrder = arrayMove([...order], order.indexOf(active.id as string), order.indexOf(over.id as string))
    reorderTasks(storyId, newOrder)
    setActiveDragId(null)
    startTransition(async () => {
      const result = await reorderTasksAction(storyId, newOrder)
      if (!result.success) { rollbackTasks(storyId, prevOrder); toast.error('Volgorde opslaan mislukt') }
    })
  }

  function handleStatusToggle(task: Task) {
    startTransition(async () => {
      await updateTaskStatusAction(task.id, STATUS_CYCLE[task.status] ?? 'TO_DO')
    })
  }

  function handleDelete(id: string) {
    startTransition(async () => {
      const result = await deleteTaskAction(id)
      if (result && 'error' in result) toast.error(result.error ?? 'Verwijderen mislukt')
    })
  }

  return (
    <div className="flex flex-col h-full">
      <PanelNavBar
        title="Taken"
        actions={
          <>
            <span className="text-xs text-muted-foreground">{doneCount}/{orderedTasks.length} klaar</span>
            {!isDemo && (
              <Button size="sm" className="h-7 text-xs" onClick={() => setCreating(true)}>+ Taak</Button>
            )}
          </>
        }
      />

      <div className="flex-1 overflow-y-auto">
        {creating && (
          <CreateTaskForm storyId={storyId} sprintId={sprintId} onDone={() => setCreating(false)} />
        )}

        {orderedTasks.length === 0 && !creating ? (
          <div className="text-center mt-8 space-y-3">
            <p className="text-sm text-muted-foreground">Geen taken voor deze story.</p>
            {!isDemo && <Button size="sm" variant="outline" onClick={() => setCreating(true)}>Maak eerste taak aan</Button>}
          </div>
        ) : (
          <DndContext
            id="task-list"
            sensors={sensors}
            collisionDetection={closestCenter}
            onDragStart={e => setActiveDragId(e.active.id as string)}
            onDragEnd={handleDragEnd}
          >
            <SortableContext items={orderedTasks.map(t => t.id)} strategy={verticalListSortingStrategy}>
              {orderedTasks.map((task, idx) => (
                <SortableTaskRow
                  key={task.id}
                  task={task}
                  code={deriveTaskCode(storyCode, idx + 1)}
                  isDemo={isDemo}
                  onStatusToggle={() => handleStatusToggle(task)}
                  onDelete={() => handleDelete(task.id)}
                />
              ))}
            </SortableContext>
            <DragOverlay>
              {activeDragId && taskMap[activeDragId] && (
                <div className={cn(
                  'rounded border border-primary px-3 py-2 bg-surface-container shadow-lg opacity-90 text-sm',
                  PRIORITY_BORDER[taskMap[activeDragId].priority]
                )}>
                  {taskMap[activeDragId].title}
                </div>
              )}
            </DragOverlay>
          </DndContext>
        )}
      </div>
    </div>
  )
}
