'use client'

import { useState, useTransition, useEffect } from 'react'
import {
  DndContext,
  DragEndEvent,
  DragOverlay,
  DragStartEvent,
  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 { Badge } from '@/components/ui/badge'
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
import { PanelNavBar } from '@/components/shared/panel-nav-bar'
import { useSelectionStore } from '@/stores/selection-store'
import { usePlannerStore } from '@/stores/planner-store'
import { useBacklogStore } from '@/stores/backlog-store'
import { deletePbiAction } from '@/actions/pbis'
import { reorderPbisAction, updatePbiPriorityAction } from '@/actions/stories'
import { cn } from '@/lib/utils'
import { PbiDialog, type PbiDialogState } from './pbi-dialog'
import { BacklogCard } from './backlog-card'
import { EmptyPanel } from './empty-panel'
import { DemoTooltip } from '@/components/shared/demo-tooltip'
import { PRIORITY_COLORS } from '@/components/shared/priority-select'
import { PBI_STATUS_LABELS, PBI_STATUS_COLORS } from '@/components/shared/pbi-status-select'
import type { PbiStatusApi } from '@/lib/task-status'

const PRIORITY_LABELS: Record<number, string> = {
  1: 'Kritiek',
  2: 'Hoog',
  3: 'Gemiddeld',
  4: 'Laag',
}


type SortMode = 'priority' | 'code' | 'date'

const SORT_OPTIONS: Array<{ value: SortMode; label: string }> = [
  { value: 'priority', label: 'Prioriteit' },
  { value: 'code', label: 'Code' },
  { value: 'date', label: 'Datum' },
]

const PRIORITY_OPTIONS: Array<{ value: number | 'all'; label: string }> = [
  { value: 'all', label: 'Alle' },
  { value: 1, label: 'Kritiek' },
  { value: 2, label: 'Hoog' },
  { value: 3, label: 'Gemiddeld' },
  { value: 4, label: 'Laag' },
]

const STATUS_OPTIONS: Array<{ value: PbiStatusApi | 'all'; label: string }> = [
  { value: 'all', label: 'Alle' },
  { value: 'ready', label: 'Klaar' },
  { value: 'blocked', label: 'Geblokkeerd' },
  { value: 'done', label: 'Afgerond' },
]

function FilterPills<T extends string | number>({
  label,
  options,
  value,
  onChange,
}: {
  label: string
  options: Array<{ value: T; label: string }>
  value: T
  onChange: (v: T) => void
}) {
  return (
    <div className="space-y-1.5">
      <p className="text-xs font-medium text-muted-foreground">{label}</p>
      <div className="flex flex-wrap gap-1.5">
        {options.map((opt) => (
          <button
            key={String(opt.value)}
            type="button"
            onClick={() => onChange(opt.value)}
            className={cn(
              'text-xs px-2.5 py-1 rounded-full border transition-colors',
              value === opt.value
                ? 'bg-primary text-primary-foreground border-primary'
                : 'bg-transparent border-border hover:bg-surface-container'
            )}
          >
            {opt.label}
          </button>
        ))}
      </div>
    </div>
  )
}

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

interface PbiListProps {
  productId: string
  isDemo: boolean
}

// --- Sortable PBI row ---
function SortablePbiRow({
  pbi,
  isSelected,
  isDemo,
  onSelect,
  onEdit,
  onDelete,
}: {
  pbi: Pbi
  isSelected: boolean
  isDemo: boolean
  onSelect: () => void
  onEdit: () => void
  onDelete: () => void
}) {
  const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
    id: pbi.id,
  })

  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
  }

  return (
    <BacklogCard
      ref={setNodeRef}
      style={style}
      {...attributes}
      {...listeners}
      title={pbi.title}
      code={pbi.code}
      priority={pbi.priority}
      isSelected={isSelected}
      isDragging={isDragging}
      role="button"
      tabIndex={0}
      aria-selected={isSelected}
      onClick={onSelect}
      onKeyDown={(e: React.KeyboardEvent) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onSelect() } }}
      badge={
        <Badge className={cn('text-xs font-normal', PBI_STATUS_COLORS[pbi.status])}>
          {PBI_STATUS_LABELS[pbi.status]}
        </Badge>
      }
      actions={
        <div className="flex items-center gap-1">
          <DemoTooltip show={isDemo}>
            <button
              onClick={(e) => { e.stopPropagation(); if (!isDemo) onEdit() }}
              className="border border-border rounded px-1.5 py-0.5 text-xs text-muted-foreground hover:text-foreground hover:bg-surface-container transition-colors disabled:opacity-40 disabled:cursor-not-allowed"
              aria-label="Bewerk PBI"
              disabled={isDemo}
            >
              ✎
            </button>
          </DemoTooltip>
          <DemoTooltip show={isDemo}>
            <button
              onClick={(e) => { e.stopPropagation(); if (!isDemo) onDelete() }}
              className="text-muted-foreground hover:text-error text-xs disabled:opacity-40 disabled:cursor-not-allowed"
              aria-label="Verwijder PBI"
              disabled={isDemo}
            >
              ×
            </button>
          </DemoTooltip>
        </div>
      }
    />
  )
}

// --- Main component ---
export function PbiList({ productId, isDemo }: PbiListProps) {
  const pbis = useBacklogStore((s) => s.pbis)
  const { selectedPbiId, selectPbi } = useSelectionStore()
  const { pbiOrder, pbiPriority, initPbis, reorderPbis, rollbackPbis, updatePbiPriority } = usePlannerStore()
  // Defaults match SSR; persisted values applied post-mount in the loader effect below.
  // This avoids hydration mismatch when localStorage holds non-default values.
  const [filterPriority, setFilterPriority] = useState<number | 'all'>('all')
  const [filterStatus, setFilterStatus] = useState<PbiStatusApi | 'all'>('all')
  const [sortMode, setSortMode] = useState<SortMode>('priority')
  const [prefsLoaded, setPrefsLoaded] = useState(false)
  const [dialogState, setDialogState] = useState<PbiDialogState | null>(null)
  const [activeDragId, setActiveDragId] = useState<string | null>(null)
  const [, startTransition] = useTransition()

  // Load persisted preferences once after mount (client-only).
  // setState calls here are intentional: hydrating from localStorage on first paint.
  useEffect(() => {
    const savedSort = localStorage.getItem('scrum4me:pbi_sort')
    if (savedSort === 'priority' || savedSort === 'code' || savedSort === 'date') {
      // eslint-disable-next-line react-hooks/set-state-in-effect
      setSortMode(savedSort)
    }
    const savedPriority = localStorage.getItem('scrum4me:pbi_filter_priority')
    if (savedPriority && savedPriority !== 'all') {
      const n = parseInt(savedPriority, 10)
      if (Number.isInteger(n) && n >= 1 && n <= 4) setFilterPriority(n)
    }
    const savedStatus = localStorage.getItem('scrum4me:pbi_filter_status')
    if (savedStatus === 'ready' || savedStatus === 'blocked' || savedStatus === 'done') {
      setFilterStatus(savedStatus)
    }
    setPrefsLoaded(true)
  }, [])

  // Persist on change, but skip the initial render so we don't overwrite saved values with defaults.
  useEffect(() => { if (prefsLoaded) localStorage.setItem('scrum4me:pbi_sort', sortMode) }, [sortMode, prefsLoaded])
  useEffect(() => { if (prefsLoaded) localStorage.setItem('scrum4me:pbi_filter_priority', String(filterPriority)) }, [filterPriority, prefsLoaded])
  useEffect(() => { if (prefsLoaded) localStorage.setItem('scrum4me:pbi_filter_status', filterStatus) }, [filterStatus, prefsLoaded])

  // Sync server data into store — use stable string dep to avoid infinite loop
  const pbiIdKey = pbis.map(p => p.id).join(',')
  useEffect(() => {
    initPbis(productId, pbiIdKey ? pbiIdKey.split(',') : [])
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [productId, pbiIdKey])

  // Build ordered PBI list from store (or fall back to server order)
  const order = pbiOrder[productId] ?? pbis.map(p => p.id)
  const pbiMap = Object.fromEntries(pbis.map(p => [p.id, p]))

  // Apply priority overrides from store
  const orderedPbis = order
    .map(id => pbiMap[id])
    .filter(Boolean)
    .map(p => ({ ...p, priority: pbiPriority[p.id] ?? p.priority }))

  const base = orderedPbis.filter(p => {
    if (filterPriority !== 'all' && p.priority !== filterPriority) return false
    if (filterStatus !== 'all' && p.status !== filterStatus) return false
    return true
  })

  const activeFilterCount =
    (filterPriority !== 'all' ? 1 : 0) +
    (filterStatus !== 'all' ? 1 : 0) +
    (sortMode !== 'priority' ? 1 : 0)

  const filtered = [...base].sort((a, b) => {
    if (sortMode === 'code') {
      return (a.code ?? '').localeCompare(b.code ?? '', 'nl', { numeric: true })
    }
    if (sortMode === 'date') {
      return new Date(b.created_at).getTime() - new Date(a.created_at).getTime()
    }
    // priority: sort by priority asc, then drag-and-drop sort_order within group
    return a.priority !== b.priority ? a.priority - b.priority : 0
  })

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

  function handleDragStart(event: DragStartEvent) {
    setActiveDragId(event.active.id as string)
  }

  function handleDragEnd(event: DragEndEvent) {
    setActiveDragId(null)
    const { active, over } = event
    if (!over || active.id === over.id) return

    const activePbi = pbiMap[active.id as string]
    const overPbi = pbiMap[over.id as string]
    if (!activePbi || !overPbi) return

    const prevOrder = [...order]
    const oldIndex = order.indexOf(active.id as string)
    const newIndex = order.indexOf(over.id as string)
    const newOrder = arrayMove([...order], oldIndex, newIndex)

    // Optimistic update
    reorderPbis(productId, newOrder)

    const priorityChanged = activePbi.priority !== overPbi.priority

    startTransition(async () => {
      if (priorityChanged) {
        updatePbiPriority(active.id as string, overPbi.priority)
        const result = await updatePbiPriorityAction(active.id as string, overPbi.priority, productId)
        if (!result.success) {
          rollbackPbis(productId, prevOrder)
          toast.error('Prioriteit opslaan mislukt')
        }
      } else {
        const result = await reorderPbisAction(productId, newOrder)
        if (!result.success) {
          rollbackPbis(productId, prevOrder)
          toast.error('Volgorde opslaan mislukt')
        }
      }
    })
  }

  function handleDelete(id: string) {
    startTransition(async () => {
      await deletePbiAction(id)
      if (selectedPbiId === id) selectPbi(null)
    })
  }

  const activePbi = activeDragId ? pbiMap[activeDragId] : null

  return (
    <div className="flex flex-col h-full">
      <PanelNavBar
        title="Product Backlog"
        actions={
          <>
            {filterPriority !== 'all' && (
              <button
                onClick={() => setFilterPriority('all')}
                className="flex items-center gap-1 text-xs text-primary hover:underline"
                aria-label="Wis prioriteitsfilter"
              >
                <Badge className={cn('text-xs', PRIORITY_COLORS[filterPriority])}>
                  {PRIORITY_LABELS[filterPriority]}
                </Badge>
                <span>×</span>
              </button>
            )}
            {filterStatus !== 'all' && (
              <button
                onClick={() => setFilterStatus('all')}
                className="flex items-center gap-1 text-xs text-primary hover:underline"
                aria-label="Wis statusfilter"
              >
                <Badge className={cn('text-xs', PBI_STATUS_COLORS[filterStatus])}>
                  {PBI_STATUS_LABELS[filterStatus]}
                </Badge>
                <span>×</span>
              </button>
            )}
            <Popover>
              <PopoverTrigger
                render={
                  <Button variant="outline" size="sm" className="h-7 text-xs">
                    {`Filters${activeFilterCount > 0 ? ` (${activeFilterCount})` : ''}`}
                  </Button>
                }
              />
              <PopoverContent align="end" className="w-72 space-y-4">
                <FilterPills
                  label="Sorteren op"
                  options={SORT_OPTIONS}
                  value={sortMode}
                  onChange={setSortMode}
                />
                <FilterPills
                  label="Prioriteit"
                  options={PRIORITY_OPTIONS}
                  value={filterPriority}
                  onChange={setFilterPriority}
                />
                <FilterPills
                  label="Status"
                  options={STATUS_OPTIONS}
                  value={filterStatus}
                  onChange={setFilterStatus}
                />
                <div className="flex justify-end pt-1 border-t border-border">
                  <Button
                    type="button"
                    variant="ghost"
                    size="sm"
                    className="h-7 text-xs"
                    disabled={activeFilterCount === 0}
                    onClick={() => {
                      setFilterPriority('all')
                      setFilterStatus('all')
                      setSortMode('priority')
                    }}
                  >
                    Wis filters
                  </Button>
                </div>
              </PopoverContent>
            </Popover>
            <DemoTooltip show={isDemo}>
              <Button
                size="sm"
                className="h-7 text-xs"
                disabled={isDemo}
                onClick={() => !isDemo && setDialogState({ mode: 'create', productId, defaultPriority: 2 })}
              >
                + PBI
              </Button>
            </DemoTooltip>
          </>
        }
      />

      <div className="flex-1 overflow-y-auto">
        {pbis.length === 0 ? (
          <EmptyPanel
            message="Nog geen PBI's aangemaakt."
            action={{ label: 'Maak je eerste PBI aan', onClick: () => setDialogState({ mode: 'create', productId, defaultPriority: 2 }), disabled: isDemo }}
          />
        ) : (
          <DndContext
            id="pbi-list"
            sensors={sensors}
            collisionDetection={closestCenter}
            onDragStart={handleDragStart}
            onDragEnd={handleDragEnd}
          >
            <SortableContext
              items={filtered.map(p => p.id)}
              strategy={verticalListSortingStrategy}
            >
              <div className="p-3 flex flex-col gap-2">
                {filtered.map(pbi => (
                  <SortablePbiRow
                    key={pbi.id}
                    pbi={pbi}
                    isSelected={selectedPbiId === pbi.id}
                    isDemo={isDemo}
                    onSelect={() => selectPbi(pbi.id)}
                    onEdit={() => setDialogState({ mode: 'edit', productId, pbi })}
                    onDelete={() => handleDelete(pbi.id)}
                  />
                ))}
              </div>
            </SortableContext>

            <DragOverlay>
              {activePbi && (
                <BacklogCard
                  title={activePbi.title}
                  priority={activePbi.priority}
                  className="border-primary shadow-xl opacity-90"
                />
              )}
            </DragOverlay>
          </DndContext>
        )}
      </div>

      <PbiDialog
        state={dialogState}
        onClose={() => setDialogState(null)}
      />
    </div>
  )
}
