'use client'

import { useState } from 'react'
import { trpc } from '@/lib/trpc/client'
import { toast } from 'sonner'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
import { Skeleton } from '@/components/ui/skeleton'
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
  AlertDialogTrigger,
} from '@/components/ui/alert-dialog'
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select'
import { ListOrdered, Loader2, PlusCircle } from 'lucide-react'
import { formatEnumLabel } from '@/lib/utils'
import type { CompetitionCategory } from '@prisma/client'

interface Props {
  programId: string
}

function AddToWaitlistForm({ programId }: { programId: string }) {
  const utils = trpc.useUtils()
  const [category, setCategory] = useState<string>('')
  const [projectId, setProjectId] = useState<string>('')

  const { data: candidatesData, isLoading: loadingCandidates } =
    trpc.finalist.listEnrollmentCandidates.useQuery({ programId })

  const { data: waitlistData } = trpc.finalist.listWaitlist.useQuery({ programId })

  const addMutation = trpc.finalist.addToWaitlist.useMutation({
    onSuccess: () => {
      toast.success('Project added to waitlist')
      utils.finalist.listWaitlist.invalidate({ programId })
      utils.finalist.listEnrollmentCandidates.invalidate({ programId })
      setProjectId('')
    },
    onError: (err) => toast.error(err.message),
  })

  // Build set of project IDs already on the waitlist
  const waitlistedProjectIds = new Set(
    (waitlistData ?? [])
      .filter((e) => e.status === 'WAITING' || e.status === 'PROMOTED')
      .map((e) => e.projectId),
  )

  // Candidates per selected category — exclude confirmed/waitlisted
  const categoryData = candidatesData?.categories.find((c) => c.category === category)
  const availableCandidates = (categoryData?.candidates ?? []).filter(
    (c) =>
      !waitlistedProjectIds.has(c.projectId) &&
      c.confirmationStatus !== 'CONFIRMED',
  )

  // Category options (only categories that have candidates)
  const categoryOptions = (candidatesData?.categories ?? []).filter(
    (c) =>
      c.candidates.some(
        (p) =>
          !waitlistedProjectIds.has(p.projectId) &&
          p.confirmationStatus !== 'CONFIRMED',
      ),
  )

  // Derive the next rank for the selected category
  const currentMaxRank = Math.max(
    0,
    ...(waitlistData ?? [])
      .filter((e) => e.category === category)
      .map((e) => e.rank),
  )
  const nextRank = currentMaxRank + 1

  const canSubmit = !!category && !!projectId && !addMutation.isPending

  if (loadingCandidates) return <Skeleton className="h-10 w-full" />

  return (
    <div className="border-t pt-4">
      <div className="mb-2 flex items-center gap-2 text-sm font-medium">
        <PlusCircle className="text-muted-foreground h-4 w-4" />
        Add to waitlist
      </div>
      <div className="flex flex-wrap items-end gap-2">
        <div className="min-w-[160px]">
          <Select
            value={category}
            onValueChange={(v) => {
              setCategory(v)
              setProjectId('')
            }}
          >
            <SelectTrigger className="h-9 text-sm">
              <SelectValue placeholder="Category" />
            </SelectTrigger>
            <SelectContent>
              {categoryOptions.length === 0 ? (
                <SelectItem value="__none__" disabled>
                  No eligible categories
                </SelectItem>
              ) : (
                categoryOptions.map((c) => (
                  <SelectItem key={c.category} value={c.category}>
                    {formatEnumLabel(c.category)}
                  </SelectItem>
                ))
              )}
            </SelectContent>
          </Select>
        </div>
        <div className="min-w-[220px] flex-1">
          <Select
            value={projectId}
            onValueChange={setProjectId}
            disabled={!category || availableCandidates.length === 0}
          >
            <SelectTrigger className="h-9 text-sm">
              <SelectValue placeholder={category ? 'Select project' : 'Choose category first'} />
            </SelectTrigger>
            <SelectContent>
              {availableCandidates.length === 0 ? (
                <SelectItem value="__none__" disabled>
                  No eligible projects
                </SelectItem>
              ) : (
                availableCandidates.map((c) => (
                  <SelectItem key={c.projectId} value={c.projectId}>
                    {c.title}
                    {c.country ? ` · ${c.country}` : ''}
                  </SelectItem>
                ))
              )}
            </SelectContent>
          </Select>
        </div>
        <Button
          size="sm"
          disabled={!canSubmit}
          onClick={() =>
            addMutation.mutate({
              programId,
              category: category as CompetitionCategory,
              projectId,
              rank: nextRank,
            })
          }
        >
          {addMutation.isPending ? (
            <Loader2 className="h-4 w-4 animate-spin" />
          ) : (
            'Add at end'
          )}
        </Button>
      </div>
    </div>
  )
}

const STATUS_LABEL: Record<string, { label: string; variant: 'default' | 'secondary' | 'outline' | 'destructive' }> = {
  WAITING: { label: 'Waiting', variant: 'outline' },
  PROMOTED: { label: 'Promoted', variant: 'default' },
  USED: { label: 'Used', variant: 'secondary' },
}

export function WaitlistCard({ programId }: Props) {
  const utils = trpc.useUtils()
  const { data, isLoading } = trpc.finalist.listWaitlist.useQuery({ programId })

  const promoteMutation = trpc.finalist.manualPromote.useMutation({
    onSuccess: () => {
      toast.success('Waitlist entry promoted — confirmation email sent')
      utils.finalist.listWaitlist.invalidate({ programId })
      utils.finalist.listCategoryCounts.invalidate({ programId })
    },
    onError: (err) => toast.error(err.message),
  })

  if (isLoading) return <Skeleton className="h-44 w-full rounded-md" />

  const byCategory = new Map<CompetitionCategory, typeof data>()
  for (const entry of data ?? []) {
    const list = byCategory.get(entry.category) ?? []
    list.push(entry)
    byCategory.set(entry.category, list)
  }

  if (!data || data.length === 0) {
    return (
      <Card>
        <CardHeader>
          <div className="flex items-center gap-2">
            <ListOrdered className="text-muted-foreground h-4 w-4" />
            <CardTitle className="text-base">Waitlist</CardTitle>
          </div>
          <CardDescription>
            Per-category ranked waitlist. Auto-cascades when a finalist declines or expires.
          </CardDescription>
        </CardHeader>
        <CardContent className="space-y-4">
          <p className="text-muted-foreground py-4 text-center text-sm">
            No waitlist entries yet.
          </p>
          <AddToWaitlistForm programId={programId} />
        </CardContent>
      </Card>
    )
  }

  return (
    <Card>
      <CardHeader>
        <div className="flex items-center gap-2">
          <ListOrdered className="text-muted-foreground h-4 w-4" />
          <CardTitle className="text-base">Waitlist</CardTitle>
        </div>
        <CardDescription>
          Per-category ranked waitlist. Auto-cascades when a finalist declines or expires. You can
          manually promote out of order — overrides are audit-logged.
        </CardDescription>
      </CardHeader>
      <CardContent className="space-y-5">
        {Array.from(byCategory.entries()).map(([category, entries]) => (
          <div key={category}>
            <div className="text-muted-foreground mb-2 text-xs font-medium uppercase tracking-wide">
              {formatEnumLabel(category)}
            </div>
            <div className="space-y-2">
              {(entries ?? []).map((entry) => {
                const badge = STATUS_LABEL[entry.status] ?? { label: entry.status, variant: 'outline' as const }
                const canPromote = entry.status === 'WAITING'
                const isPending =
                  promoteMutation.isPending && promoteMutation.variables?.waitlistEntryId === entry.id
                return (
                  <div
                    key={entry.id}
                    className="flex items-center justify-between gap-3 rounded-md border p-3"
                  >
                    <div className="flex items-center gap-3">
                      <div className="bg-muted flex h-8 w-8 items-center justify-center rounded-full text-sm font-semibold tabular-nums">
                        {entry.rank}
                      </div>
                      <div className="min-w-0">
                        <div className="font-medium">{entry.project.title}</div>
                        <div className="text-muted-foreground text-xs">
                          {entry.project.country ?? '—'}
                        </div>
                      </div>
                    </div>
                    <div className="flex items-center gap-2">
                      <Badge variant={badge.variant} className="text-xs">
                        {badge.label}
                      </Badge>
                      {canPromote && (
                        <AlertDialog>
                          <AlertDialogTrigger asChild>
                            <Button size="sm" variant="outline" disabled={isPending}>
                              {isPending ? (
                                <Loader2 className="h-4 w-4 animate-spin" />
                              ) : (
                                'Promote'
                              )}
                            </Button>
                          </AlertDialogTrigger>
                          <AlertDialogContent>
                            <AlertDialogHeader>
                              <AlertDialogTitle>Promote this team out of order?</AlertDialogTitle>
                              <AlertDialogDescription>
                                {entry.project.title} (rank #{entry.rank}) will be promoted into a
                                finalist slot. A confirmation email will be sent to the team lead
                                with a 24-hour window. This override is audit-logged.
                              </AlertDialogDescription>
                            </AlertDialogHeader>
                            <AlertDialogFooter>
                              <AlertDialogCancel>Cancel</AlertDialogCancel>
                              <AlertDialogAction
                                onClick={() =>
                                  promoteMutation.mutate({
                                    waitlistEntryId: entry.id,
                                    windowHours: 24,
                                  })
                                }
                              >
                                Promote
                              </AlertDialogAction>
                            </AlertDialogFooter>
                          </AlertDialogContent>
                        </AlertDialog>
                      )}
                    </div>
                  </div>
                )
              })}
            </div>
          </div>
        ))}
        <AddToWaitlistForm programId={programId} />
      </CardContent>
    </Card>
  )
}
