'use client'

import { useState, useTransition, useActionState, useRef } from 'react'
import { Button } from '@/components/ui/button'
import { Textarea } from '@/components/ui/textarea'
import {
  Dialog,
  DialogContent,
  DialogTitle,
} from '@/components/ui/dialog'
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from '@/components/ui/alert-dialog'
import { toast } from 'sonner'
import { DemoTooltip } from '@/components/shared/demo-tooltip'
import {
  useDirtyCloseGuard,
  DirtyCloseGuardDialog,
} from '@/components/shared/use-dirty-close-guard'
import { useDialogSubmitShortcut } from '@/components/shared/use-dialog-submit-shortcut'
import {
  entityDialogContentClasses,
  entityDialogFooterClasses,
  entityDialogHeaderClasses,
} from '@/components/shared/entity-dialog-layout'
import { updateSprintGoalAction, updateSprintDatesAction, completeSprintAction, setAllSprintTasksDoneAction } from '@/actions/sprints'
import type { SprintStory } from './sprint-backlog'
import { debugProps } from '@/lib/debug'
import { SprintSwitcher } from '@/components/shared/sprint-switcher'
import type { SprintSwitcherItem } from '@/lib/sprint-switcher-data'

interface Sprint {
  id: string
  code: string
  sprint_goal: string
  status: string
  start_date: Date | null
  end_date: Date | null
}

interface SprintHeaderProps {
  productId: string
  productName: string
  sprint: Sprint
  isDemo: boolean
  sprintStories: SprintStory[]
  switcherSprints: SprintSwitcherItem[]
  switcherActiveSprint: SprintSwitcherItem | null
  switcherBuildingSprintIds: string[]
}

interface ActionResult {
  success?: boolean
  error?: string
  code?: number
  fieldErrors?: Record<string, string[]>
}

function toDateInputValue(d: Date | null) {
  if (!d) return ''
  return d.toISOString().slice(0, 10)
}

export function SprintHeader({ productId, productName, sprint, isDemo, sprintStories, switcherSprints, switcherActiveSprint, switcherBuildingSprintIds }: SprintHeaderProps) {
  const [editingGoal, setEditingGoal] = useState(false)
  const [editingDates, setEditingDates] = useState(false)
  const [completeOpen, setCompleteOpen] = useState(false)
  const [decisions, setDecisions] = useState<Record<string, 'DONE' | 'OPEN'>>({})
  const [isCompleting, startCompleting] = useTransition()
  const [showAllDoneConfirm, setShowAllDoneConfirm] = useState(false)
  const [isSettingAllDone, startSettingAllDone] = useTransition()
  const [datesDirty, setDatesDirty] = useState(false)
  const datesFormRef = useRef<HTMLFormElement>(null)

  const [, goalFormAction, goalPending] = useActionState<ActionResult | undefined, FormData>(
    async (_prev, fd) => {
      const result = await updateSprintGoalAction(_prev, fd) as ActionResult
      if (result?.success) { setEditingGoal(false); toast.success('Sprint goal opgeslagen') }
      else if (result?.error) toast.error(result.error)
      return result
    },
    undefined,
  )

  const [datesState, datesFormAction, datesPending] = useActionState<ActionResult | undefined, FormData>(
    async (_prev, fd) => {
      const result = await updateSprintDatesAction(_prev, fd) as ActionResult
      if (result?.success) { setEditingDates(false); setDatesDirty(false); toast.success('Sprint datums opgeslagen') }
      else if (result?.code !== 422 && result?.error) toast.error(result.error)
      return result
    },
    undefined,
  )

  const datesFieldError = (field: string) => datesState?.fieldErrors?.[field]?.[0]

  const datesCloseGuard = useDirtyCloseGuard(datesDirty, () => setEditingDates(false))
  const datesKeyDown = useDialogSubmitShortcut(() => datesFormRef.current?.requestSubmit())

  function setDecision(storyId: string, value: 'DONE' | 'OPEN') {
    setDecisions(prev => ({ ...prev, [storyId]: value }))
  }

  function handleComplete() {
    const finalDecisions: Record<string, 'DONE' | 'OPEN'> = {}
    sprintStories.forEach(s => {
      finalDecisions[s.id] = decisions[s.id] ?? 'OPEN'
    })

    startCompleting(async () => {
      const result = await completeSprintAction(sprint.id, finalDecisions)
      if ('error' in result) toast.error(result.error ?? 'Sprint afronden mislukt')
      else { toast.success('Sprint afgerond'); setCompleteOpen(false) }
    })
  }

  function handleAllDone() {
    startSettingAllDone(async () => {
      const result = await setAllSprintTasksDoneAction(sprint.id)
      if (!result.ok) {
        toast.error(result.error ?? 'Alles op done mislukt')
      } else {
        const allDone: Record<string, 'DONE' | 'OPEN'> = {}
        sprintStories.forEach(s => { allDone[s.id] = 'DONE' })
        setDecisions(allDone)
      }
      setShowAllDoneConfirm(false)
    })
  }

  return (
    <div className="px-4 py-3 border-b border-border bg-surface-container-low shrink-0" {...debugProps('sprint-header', 'SprintHeader', 'components/sprint/sprint-header.tsx')}>
      <div className="flex items-center gap-4">
        <div className="min-w-0 flex-1">
          <div className="flex items-center gap-2">
            <span className="text-xs text-muted-foreground">{productName}</span>
            <span className="text-muted-foreground">›</span>
            <span className="text-xs font-medium text-primary">Sprint actief</span>
            <span className="text-muted-foreground">·</span>
            <span className="text-xs font-mono text-muted-foreground">{sprint.code}</span>
          </div>

          {editingGoal ? (
            <form action={goalFormAction} className="flex gap-2 mt-1">
              <input type="hidden" name="id" value={sprint.id} />
              <Textarea name="sprint_goal" defaultValue={sprint.sprint_goal} rows={2} className="text-sm flex-1" autoFocus />
              <div className="flex flex-col gap-1">
                <Button type="submit" size="sm" disabled={goalPending}>
                  {goalPending ? 'Opslaan…' : 'Opslaan'}
                </Button>
                <Button type="button" size="sm" variant="ghost" aria-label="Annuleer bewerken" onClick={() => setEditingGoal(false)}>×</Button>
              </div>
            </form>
          ) : (
            <button onClick={() => !isDemo && setEditingGoal(true)} className="text-left mt-0.5 group" data-debug-id="sprint-header__title">
              <p className="text-sm font-medium text-foreground group-hover:text-primary transition-colors">
                {sprint.sprint_goal}
              </p>
            </button>
          )}
        </div>

        <div className="shrink-0">
          <SprintSwitcher
            productId={productId}
            sprints={switcherSprints}
            activeSprint={switcherActiveSprint}
            buildingSprintIds={switcherBuildingSprintIds}
          />
        </div>

        <div className="flex items-center justify-end gap-2 flex-1 shrink-0" data-debug-id="sprint-header__actions">
          <DemoTooltip show={isDemo}>
            <Button size="sm" variant="ghost" disabled={isDemo} className="text-muted-foreground" data-debug-id="sprint-header__dates" onClick={() => !isDemo && setEditingDates(true)}>
              {sprint.start_date && sprint.end_date
                ? `${toDateInputValue(sprint.start_date)} → ${toDateInputValue(sprint.end_date)}`
                : 'Datums instellen'}
            </Button>
          </DemoTooltip>
          <DemoTooltip show={isDemo}>
            <Button size="sm" variant="outline" disabled={isDemo} className="border-warning/40 text-warning hover:bg-warning/10" onClick={() => setCompleteOpen(true)}>
              Sprint afronden
            </Button>
          </DemoTooltip>
        </div>
      </div>

      {/* Dates edit dialog */}
      <Dialog open={editingDates} onOpenChange={(o) => { if (!o) datesCloseGuard.attemptClose(); else setEditingDates(o) }}>
        <DialogContent
          showCloseButton={false}
          onKeyDown={datesKeyDown}
          className={entityDialogContentClasses}
        >
          <div className={entityDialogHeaderClasses}>
            <DialogTitle className="text-xl font-semibold">Sprint datums instellen</DialogTitle>
          </div>
          <form
            ref={datesFormRef}
            id="sprint-dates-form"
            action={datesFormAction}
            onChange={() => setDatesDirty(true)}
            className="flex-1 overflow-y-auto px-6 py-6 space-y-6"
          >
            <input type="hidden" name="id" value={sprint.id} />
            <div className="grid grid-cols-2 gap-3">
              <div className="space-y-1.5">
                <label className="text-sm font-medium text-foreground">Startdatum</label>
                <input type="date" name="start_date" defaultValue={toDateInputValue(sprint.start_date)} className="w-full rounded-md border border-border bg-surface-container px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-primary" />
                {datesFieldError('start_date') && (
                  <p className="text-xs text-error">{datesFieldError('start_date')}</p>
                )}
              </div>
              <div className="space-y-1.5">
                <label className="text-sm font-medium text-foreground">Einddatum</label>
                <input type="date" name="end_date" defaultValue={toDateInputValue(sprint.end_date)} className="w-full rounded-md border border-border bg-surface-container px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-primary" />
                {datesFieldError('end_date') && (
                  <p className="text-xs text-error">{datesFieldError('end_date')}</p>
                )}
              </div>
            </div>
          </form>
          <div className={entityDialogFooterClasses}>
            <div className="flex gap-2 justify-end">
              <Button type="button" variant="ghost" onClick={datesCloseGuard.attemptClose} disabled={datesPending}>
                Annuleren
              </Button>
              <Button type="submit" form="sprint-dates-form" disabled={datesPending}>
                {datesPending ? '…' : 'Opslaan'}
              </Button>
            </div>
          </div>
        </DialogContent>
      </Dialog>

      <DirtyCloseGuardDialog guard={datesCloseGuard} />

      {/* Complete sprint dialog */}
      <Dialog open={completeOpen} onOpenChange={setCompleteOpen}>
        <DialogContent showCloseButton={false} className={entityDialogContentClasses}>
          <div className={entityDialogHeaderClasses}>
            <DialogTitle className="text-xl font-semibold">Sprint afronden</DialogTitle>
          </div>
          <div className="flex-1 overflow-y-auto px-6 py-6 space-y-6">
            <p className="text-sm text-muted-foreground">
              Geef per story aan wat er mee moet gebeuren:
            </p>
            <div className="flex justify-end">
              <Button
                type="button"
                size="sm"
                variant="outline"
                className="border-status-done/40 text-status-done hover:bg-status-done/10"
                disabled={isSettingAllDone || isCompleting}
                onClick={() => setShowAllDoneConfirm(true)}
              >
                {isSettingAllDone ? 'Bezig…' : 'Alles op done'}
              </Button>
            </div>
            <div className="space-y-2">
              {sprintStories.map(story => (
                <div key={story.id} className="flex items-center justify-between gap-3 p-2 bg-surface-container-low rounded-lg">
                  {story.code && <span className="font-mono text-[11px] text-muted-foreground shrink-0">{story.code}</span>}
                  <span className="text-sm truncate flex-1">{story.title}</span>
                  <div className="flex gap-1 shrink-0">
                    <button
                      onClick={() => setDecision(story.id, 'DONE')}
                      className={`text-xs px-2 py-1 rounded transition-colors ${(decisions[story.id] ?? 'OPEN') === 'DONE' ? 'bg-status-done/20 text-status-done font-medium' : 'text-muted-foreground hover:bg-surface-container'}`}
                    >
                      Done
                    </button>
                    <button
                      onClick={() => setDecision(story.id, 'OPEN')}
                      className={`text-xs px-2 py-1 rounded transition-colors ${(decisions[story.id] ?? 'OPEN') === 'OPEN' ? 'bg-status-todo/20 text-status-todo font-medium' : 'text-muted-foreground hover:bg-surface-container'}`}
                    >
                      Terug
                    </button>
                  </div>
                </div>
              ))}
            </div>
          </div>
          <div className={entityDialogFooterClasses}>
            <div className="flex gap-2 justify-end">
              <Button variant="ghost" onClick={() => setCompleteOpen(false)} disabled={isCompleting}>
                Annuleren
              </Button>
              <DemoTooltip show={isDemo}>
                <Button disabled={isCompleting || isDemo} onClick={handleComplete}>
                  {isCompleting ? 'Bezig…' : 'Sprint afronden'}
                </Button>
              </DemoTooltip>
            </div>
          </div>
        </DialogContent>
      </Dialog>

      <AlertDialog open={showAllDoneConfirm} onOpenChange={setShowAllDoneConfirm}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>Alles op done zetten?</AlertDialogTitle>
            <AlertDialogDescription>
              Alle taken én stories in de sprint — inclusief taken met status
              REVIEW — worden op DONE gezet. De per-story toggles hieronder
              worden daarna bijgewerkt. Je kunt daarna nog per story aanpassen
              vóór je de sprint afrondt.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel disabled={isSettingAllDone}>Annuleren</AlertDialogCancel>
            <AlertDialogAction onClick={handleAllDone} disabled={isSettingAllDone}>
              {isSettingAllDone ? 'Bezig…' : 'Alles op done'}
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </div>
  )
}
