'use client'

import { useMemo, useState, useTransition } from 'react'
import { useRouter } from 'next/navigation'
import { toast } from 'sonner'
import { Button } from '@/components/ui/button'
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from '@/components/ui/alert-dialog'
import { useUserSettingsStore } from '@/stores/user-settings/store'
import { useProductWorkspaceStore } from '@/stores/product-workspace/store'
import type { PendingSprintDraft } from '@/lib/user-settings'
import { createSprintWithSelectionAction } from '@/actions/sprints'
import { debugProps } from '@/lib/debug'

interface SprintDefinitionBannerProps {
  productId: string
  draft: PendingSprintDraft
}

type DraftCounts = {
  pbiCount: number
  storyCount: number
  hasUnknownTotal: boolean
}

function computeCounts(
  draft: PendingSprintDraft,
  pbiSummary: Record<
    string,
    { totalStoryCount: number; inActiveSprintStoryCount: number }
  >,
): DraftCounts {
  let pbiCount = 0
  let storyCount = 0
  let hasUnknownTotal = false

  const seenPbis = new Set<string>()

  for (const [pbiId, intent] of Object.entries(draft.pbiIntent)) {
    if (intent === 'all') {
      seenPbis.add(pbiId)
      const summary = pbiSummary[pbiId]
      const override = draft.storyOverrides[pbiId]
      if (!summary) {
        hasUnknownTotal = true
        continue
      }
      const removed = override?.remove.length ?? 0
      storyCount += Math.max(0, summary.totalStoryCount - removed)
    }
  }

  for (const [pbiId, override] of Object.entries(draft.storyOverrides)) {
    if (override.add.length === 0) continue
    seenPbis.add(pbiId)
    storyCount += override.add.length
  }

  pbiCount = seenPbis.size
  return { pbiCount, storyCount, hasUnknownTotal }
}

export function SprintDefinitionBanner({
  productId,
  draft,
}: SprintDefinitionBannerProps) {
  const clearPendingSprintDraft = useUserSettingsStore(
    (s) => s.clearPendingSprintDraft,
  )
  const pbiSummary = useProductWorkspaceStore((s) => s.sprintMembership.pbiSummary)
  const router = useRouter()
  const [isPending, startTransition] = useTransition()
  const [confirmCancel, setConfirmCancel] = useState(false)

  const counts = useMemo(
    () => computeCounts(draft, pbiSummary),
    [draft, pbiSummary],
  )

  function handleCancel() {
    setConfirmCancel(true)
  }

  function confirmCancelAction() {
    setConfirmCancel(false)
    startTransition(async () => {
      try {
        await clearPendingSprintDraft(productId)
      } catch (err) {
        const message =
          err instanceof Error ? err.message : 'Annuleren mislukt'
        toast.error(message)
      }
    })
  }

  function handleCreate() {
    startTransition(async () => {
      const result = await createSprintWithSelectionAction({
        productId,
        metadata: {
          goal: draft.goal,
          startAt: draft.startAt,
          endAt: draft.endAt,
        },
        pbiIntent: draft.pbiIntent,
        storyOverrides: draft.storyOverrides,
      })
      if ('error' in result) {
        toast.error(result.error)
        return
      }
      const { conflicts } = result
      if (conflicts.notEligible.length > 0) {
        toast.warning(
          `${conflicts.notEligible.length} stor${
            conflicts.notEligible.length === 1 ? 'y is' : 'ies zijn'
          } overgeslagen (al in een andere sprint of afgerond).`,
        )
      } else {
        toast.success('Sprint aangemaakt')
      }
      router.refresh()
    })
  }

  const storyLabel = counts.hasUnknownTotal
    ? `${counts.storyCount}+`
    : counts.storyCount
  const pbiSuffix = counts.pbiCount === 1 ? '' : "'s"

  return (
    <div
      className="sticky top-0 z-30 bg-tertiary-container text-tertiary-container-foreground border-b border-tertiary px-4 py-2.5 flex items-center gap-4"
      {...debugProps('sprint-definition-banner')}
    >
      <div className="flex-1 min-w-0">
        <div className="flex items-baseline gap-2">
          <span className="text-sm font-medium shrink-0">
            Sprint definiëren —
          </span>
          <span className="text-sm truncate" title={draft.goal}>
            {draft.goal}
          </span>
        </div>
        <div className="text-xs opacity-80 mt-0.5">
          {counts.pbiCount} PBI{pbiSuffix} · {storyLabel} stor
          {counts.storyCount === 1 ? 'y' : 'ies'} geselecteerd
        </div>
      </div>
      <div className="flex items-center gap-2 shrink-0">
        <Button
          type="button"
          variant="ghost"
          onClick={handleCancel}
          disabled={isPending}
          data-debug-id="sprint-definition-banner__cancel"
        >
          Annuleren
        </Button>
        <Button
          type="button"
          onClick={handleCreate}
          disabled={isPending || counts.pbiCount === 0}
          data-debug-id="sprint-definition-banner__create"
        >
          Sprint aanmaken
        </Button>
      </div>
      <AlertDialog open={confirmCancel} onOpenChange={setConfirmCancel}>
        <AlertDialogContent size="sm">
          <AlertDialogHeader>
            <AlertDialogTitle>Sprint-definitie annuleren?</AlertDialogTitle>
            <AlertDialogDescription>
              Je conceptselectie gaat verloren. Het sprint-doel en de
              gemarkeerde PBI/stories worden verwijderd.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel onClick={() => setConfirmCancel(false)}>
              Doorgaan
            </AlertDialogCancel>
            <AlertDialogAction
              variant="destructive"
              onClick={confirmCancelAction}
            >
              Ja, annuleren
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </div>
  )
}
