'use client'

import { useState, useMemo, useCallback } from 'react'
import { useParams } from 'next/navigation'
import Link from 'next/link'
import type { Route } from 'next'
import { trpc } from '@/lib/trpc/client'
import { toast } from 'sonner'
import { cn } from '@/lib/utils'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
import { Skeleton } from '@/components/ui/skeleton'
import { Badge } from '@/components/ui/badge'
import { Input } from '@/components/ui/input'
import { Switch } from '@/components/ui/switch'
import { Label } from '@/components/ui/label'
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
  AlertDialogTrigger,
} from '@/components/ui/alert-dialog'
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog'
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select'
import {
  ArrowLeft,
  Save,
  Loader2,
  ChevronDown,
  Play,
  Square,
  Archive,
  Layers,
  Users,
  CalendarDays,
  BarChart3,
  ClipboardList,
  Settings,
  Zap,
  Shield,
  UserPlus,
  CheckCircle2,
  AlertTriangle,
  FileText,
  Trophy,
  Clock,
  Send,
  Download,
  Plus,
  Trash2,
  ArrowRight,
  X,
} from 'lucide-react'
import { RoundConfigForm } from '@/components/admin/competition/round-config-form'
import { ProjectStatesTable } from '@/components/admin/round/project-states-table'
import { SubmissionWindowManager } from '@/components/admin/round/submission-window-manager'
import { FileRequirementsEditor } from '@/components/admin/round/file-requirements-editor'
import { FilteringDashboard } from '@/components/admin/round/filtering-dashboard'
import { CoverageReport } from '@/components/admin/assignment/coverage-report'
import { AssignmentPreviewSheet } from '@/components/admin/assignment/assignment-preview-sheet'
import { CsvExportDialog } from '@/components/shared/csv-export-dialog'

// ── Status & type config maps ──────────────────────────────────────────────
const roundStatusConfig = {
  ROUND_DRAFT: {
    label: 'Draft',
    bgClass: 'bg-gray-100 text-gray-700',
    dotClass: 'bg-gray-500',
    description: 'Not yet active. Configure before launching.',
  },
  ROUND_ACTIVE: {
    label: 'Active',
    bgClass: 'bg-emerald-100 text-emerald-700',
    dotClass: 'bg-emerald-500 animate-pulse',
    description: 'Round is live. Projects can be processed.',
  },
  ROUND_CLOSED: {
    label: 'Closed',
    bgClass: 'bg-blue-100 text-blue-700',
    dotClass: 'bg-blue-500',
    description: 'No longer accepting changes. Results are final.',
  },
  ROUND_ARCHIVED: {
    label: 'Archived',
    bgClass: 'bg-muted text-muted-foreground',
    dotClass: 'bg-muted-foreground',
    description: 'Historical record only.',
  },
} as const

const roundTypeConfig: Record<string, { label: string; color: string; description: string }> = {
  INTAKE: { label: 'Intake', color: 'bg-gray-100 text-gray-700', description: 'Collecting applications' },
  FILTERING: { label: 'Filtering', color: 'bg-amber-100 text-amber-700', description: 'AI + manual screening' },
  EVALUATION: { label: 'Evaluation', color: 'bg-blue-100 text-blue-700', description: 'Jury evaluation & scoring' },
  SUBMISSION: { label: 'Submission', color: 'bg-purple-100 text-purple-700', description: 'Document submission' },
  MENTORING: { label: 'Mentoring', color: 'bg-teal-100 text-teal-700', description: 'Mentor-guided development' },
  LIVE_FINAL: { label: 'Live Final', color: 'bg-red-100 text-red-700', description: 'Live presentations & voting' },
  DELIBERATION: { label: 'Deliberation', color: 'bg-indigo-100 text-indigo-700', description: 'Final jury deliberation' },
}

const stateColors: Record<string, string> = {
  PENDING: 'bg-gray-400',
  IN_PROGRESS: 'bg-blue-500',
  PASSED: 'bg-green-500',
  REJECTED: 'bg-red-500',
  COMPLETED: 'bg-emerald-500',
  WITHDRAWN: 'bg-orange-400',
}

// ═══════════════════════════════════════════════════════════════════════════
// Main Page Component
// ═══════════════════════════════════════════════════════════════════════════

export default function RoundDetailPage() {
  const params = useParams()
  const roundId = params.roundId as string

  const [config, setConfig] = useState<Record<string, unknown>>({})
  const [hasChanges, setHasChanges] = useState(false)
  const [activeTab, setActiveTab] = useState('overview')
  const [previewSheetOpen, setPreviewSheetOpen] = useState(false)
  const [exportOpen, setExportOpen] = useState(false)
  const [advanceDialogOpen, setAdvanceDialogOpen] = useState(false)

  const utils = trpc.useUtils()

  // ── Core data queries ──────────────────────────────────────────────────
  const { data: round, isLoading } = trpc.round.getById.useQuery(
    { id: roundId },
    { refetchInterval: 30_000 },
  )
  const { data: projectStates } = trpc.roundEngine.getProjectStates.useQuery(
    { roundId },
    { refetchInterval: 15_000 },
  )

  const competitionId = round?.competitionId ?? ''

  const { data: juryGroups } = trpc.juryGroup.list.useQuery(
    { competitionId },
    { enabled: !!competitionId, refetchInterval: 30_000 },
  )
  const { data: fileRequirements } = trpc.file.listRequirements.useQuery(
    { roundId },
    { refetchInterval: 30_000 },
  )

  // Fetch awards linked to this round
  const { data: competition } = trpc.competition.getById.useQuery(
    { id: competitionId },
    { enabled: !!competitionId, refetchInterval: 60_000 },
  )
  const programId = competition?.programId
  const { data: awards } = trpc.specialAward.list.useQuery(
    { programId: programId! },
    { enabled: !!programId, refetchInterval: 60_000 },
  )
  const roundAwards = awards?.filter((a) => a.evaluationRoundId === roundId) ?? []

  // Sync config from server when not dirty
  if (round && !hasChanges) {
    const roundConfig = (round.configJson as Record<string, unknown>) ?? {}
    if (JSON.stringify(roundConfig) !== JSON.stringify(config)) {
      setConfig(roundConfig)
    }
  }

  // ── Mutations ──────────────────────────────────────────────────────────
  const updateMutation = trpc.round.update.useMutation({
    onSuccess: () => {
      utils.round.getById.invalidate({ id: roundId })
      toast.success('Round configuration saved')
      setHasChanges(false)
    },
    onError: (err) => toast.error(err.message),
  })

  const activateMutation = trpc.roundEngine.activate.useMutation({
    onSuccess: () => {
      utils.round.getById.invalidate({ id: roundId })
      toast.success('Round activated')
    },
    onError: (err) => toast.error(err.message),
  })

  const closeMutation = trpc.roundEngine.close.useMutation({
    onSuccess: () => {
      utils.round.getById.invalidate({ id: roundId })
      toast.success('Round closed')
    },
    onError: (err) => toast.error(err.message),
  })

  const archiveMutation = trpc.roundEngine.archive.useMutation({
    onSuccess: () => {
      utils.round.getById.invalidate({ id: roundId })
      toast.success('Round archived')
    },
    onError: (err) => toast.error(err.message),
  })

  const assignJuryMutation = trpc.round.update.useMutation({
    onSuccess: () => {
      utils.round.getById.invalidate({ id: roundId })
      toast.success('Jury group updated')
    },
    onError: (err) => toast.error(err.message),
  })

  const advanceMutation = trpc.round.advanceProjects.useMutation({
    onSuccess: (data) => {
      utils.round.getById.invalidate({ id: roundId })
      utils.roundEngine.getProjectStates.invalidate({ roundId })
      toast.success(`Advanced ${data.advancedCount} project(s) to ${data.targetRoundName}`)
      setAdvanceDialogOpen(false)
    },
    onError: (err) => toast.error(err.message),
  })

  const isTransitioning = activateMutation.isPending || closeMutation.isPending || archiveMutation.isPending

  const handleConfigChange = useCallback((newConfig: Record<string, unknown>) => {
    setConfig(newConfig)
    setHasChanges(true)
  }, [])

  const handleSave = useCallback(() => {
    updateMutation.mutate({ id: roundId, configJson: config })
  }, [roundId, config, updateMutation])

  // ── Computed values ────────────────────────────────────────────────────
  const projectCount = round?._count?.projectRoundStates ?? 0
  const stateCounts = useMemo(() =>
    projectStates?.reduce((acc: Record<string, number>, ps: any) => {
      acc[ps.state] = (acc[ps.state] || 0) + 1
      return acc
    }, {} as Record<string, number>) ?? {},
  [projectStates])
  const passedCount = stateCounts['PASSED'] ?? 0
  const juryGroup = round?.juryGroup
  const juryMemberCount = juryGroup?.members?.length ?? 0

  const isFiltering = round?.roundType === 'FILTERING'
  const isEvaluation = round?.roundType === 'EVALUATION'

  const poolLink = `/admin/projects/pool?roundId=${roundId}&competitionId=${competitionId}` as Route

  // ── Loading state ──────────────────────────────────────────────────────
  if (isLoading) {
    return (
      <div className="space-y-6">
        <div className="flex items-center gap-3">
          <Skeleton className="h-8 w-8" />
          <div className="space-y-2">
            <Skeleton className="h-7 w-64" />
            <Skeleton className="h-4 w-40" />
          </div>
        </div>
        <div className="grid gap-3 grid-cols-2 sm:grid-cols-4">
          {[1, 2, 3, 4].map((i) => <Skeleton key={i} className="h-24" />)}
        </div>
        <Skeleton className="h-10 w-full" />
        <Skeleton className="h-96 w-full" />
      </div>
    )
  }

  if (!round) {
    return (
      <div className="space-y-6">
        <div className="flex items-center gap-3">
          <Link href={'/admin/rounds' as Route}>
            <Button variant="ghost" size="icon" className="h-8 w-8" aria-label="Back">
              <ArrowLeft className="h-4 w-4" />
            </Button>
          </Link>
          <div>
            <h1 className="text-xl font-bold">Round Not Found</h1>
            <p className="text-sm text-muted-foreground">This round does not exist.</p>
          </div>
        </div>
      </div>
    )
  }

  const status = round.status as keyof typeof roundStatusConfig
  const statusCfg = roundStatusConfig[status] || roundStatusConfig.ROUND_DRAFT
  const typeCfg = roundTypeConfig[round.roundType] || roundTypeConfig.INTAKE

  // ── Readiness checklist ────────────────────────────────────────────────
  const readinessItems = [
    {
      label: 'Projects assigned',
      ready: projectCount > 0,
      detail: projectCount > 0 ? `${projectCount} projects` : 'No projects yet',
      action: projectCount === 0 ? poolLink : undefined,
      actionLabel: 'Assign Projects',
    },
    ...((isEvaluation || isFiltering)
      ? [{
          label: 'Jury group set',
          ready: !!juryGroup,
          detail: juryGroup ? `${juryGroup.name} (${juryMemberCount} members)` : 'No jury group assigned',
          action: undefined as Route | undefined,
          actionLabel: undefined as string | undefined,
        }]
      : []),
    {
      label: 'Dates configured',
      ready: !!round.windowOpenAt && !!round.windowCloseAt,
      detail:
        round.windowOpenAt && round.windowCloseAt
          ? `${new Date(round.windowOpenAt).toLocaleDateString()} \u2014 ${new Date(round.windowCloseAt).toLocaleDateString()}`
          : 'No dates set \u2014 configure in Config tab',
      action: undefined as Route | undefined,
      actionLabel: undefined as string | undefined,
    },
    {
      label: 'File requirements set',
      ready: (fileRequirements?.length ?? 0) > 0,
      detail:
        (fileRequirements?.length ?? 0) > 0
          ? `${fileRequirements?.length} requirement(s)`
          : 'No file requirements \u2014 configure in Config tab',
      action: undefined as Route | undefined,
      actionLabel: undefined as string | undefined,
    },
  ]
  const readyCount = readinessItems.filter((i) => i.ready).length

  // ═════════════════════════════════════════════════════════════════════════
  // Render
  // ═════════════════════════════════════════════════════════════════════════

  return (
    <div className="space-y-6">
      {/* ===== HEADER ===== */}
      <div className="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
        <div className="flex items-start gap-3 min-w-0">
          <Link href={'/admin/rounds' as Route} className="mt-1 shrink-0">
            <Button variant="ghost" size="icon" className="h-8 w-8" aria-label="Back to rounds">
              <ArrowLeft className="h-4 w-4" />
            </Button>
          </Link>
          <div className="min-w-0">
            <div className="flex flex-wrap items-center gap-2">
              <h1 className="text-xl font-bold tracking-tight truncate">{round.name}</h1>
              <Badge variant="secondary" className={cn('text-xs shrink-0', typeCfg.color)}>
                {typeCfg.label}
              </Badge>

              {/* Status dropdown */}
              <DropdownMenu>
                <DropdownMenuTrigger asChild>
                  <button
                    className={cn(
                      'inline-flex items-center gap-1.5 text-[11px] font-medium px-2.5 py-1 rounded-full transition-colors shrink-0',
                      statusCfg.bgClass,
                      'hover:opacity-80',
                    )}
                  >
                    <span className={cn('h-1.5 w-1.5 rounded-full', statusCfg.dotClass)} />
                    {statusCfg.label}
                    <ChevronDown className="h-3 w-3" />
                  </button>
                </DropdownMenuTrigger>
                <DropdownMenuContent align="start">
                  {status === 'ROUND_DRAFT' && (
                    <DropdownMenuItem
                      onClick={() => activateMutation.mutate({ roundId })}
                      disabled={isTransitioning}
                    >
                      <Play className="h-4 w-4 mr-2 text-emerald-600" />
                      Activate Round
                    </DropdownMenuItem>
                  )}
                  {status === 'ROUND_ACTIVE' && (
                    <DropdownMenuItem
                      onClick={() => closeMutation.mutate({ roundId })}
                      disabled={isTransitioning}
                    >
                      <Square className="h-4 w-4 mr-2 text-blue-600" />
                      Close Round
                    </DropdownMenuItem>
                  )}
                  {status === 'ROUND_CLOSED' && (
                    <>
                      <DropdownMenuItem
                        onClick={() => activateMutation.mutate({ roundId })}
                        disabled={isTransitioning}
                      >
                        <Play className="h-4 w-4 mr-2 text-emerald-600" />
                        Reactivate Round
                      </DropdownMenuItem>
                      <DropdownMenuSeparator />
                      <DropdownMenuItem
                        onClick={() => archiveMutation.mutate({ roundId })}
                        disabled={isTransitioning}
                      >
                        <Archive className="h-4 w-4 mr-2" />
                        Archive Round
                      </DropdownMenuItem>
                    </>
                  )}
                  {isTransitioning && (
                    <div className="flex items-center gap-2 px-2 py-1.5 text-xs text-muted-foreground">
                      <Loader2 className="h-3 w-3 animate-spin" />
                      Updating...
                    </div>
                  )}
                </DropdownMenuContent>
              </DropdownMenu>
            </div>
            <p className="text-sm text-muted-foreground mt-0.5">{typeCfg.description}</p>
          </div>
        </div>

        {/* Action buttons */}
        <div className="flex items-center gap-2 shrink-0 flex-wrap">
          {hasChanges && (
            <Button size="sm" onClick={handleSave} disabled={updateMutation.isPending}>
              {updateMutation.isPending ? (
                <Loader2 className="h-4 w-4 mr-1.5 animate-spin" />
              ) : (
                <Save className="h-4 w-4 mr-1.5" />
              )}
              Save Config
            </Button>
          )}
          <Link href={poolLink}>
            <Button variant="outline" size="sm">
              <Layers className="h-4 w-4 mr-1.5" />
              Project Pool
            </Button>
          </Link>
        </div>
      </div>

      {/* ===== STATS BAR ===== */}
      <div className="grid gap-3 grid-cols-2 sm:grid-cols-4">
        {/* Projects */}
        <Card>
          <CardContent className="pt-4 pb-3">
            <div className="flex items-center justify-between">
              <div className="flex items-center gap-2">
                <Layers className="h-4 w-4 text-blue-500" />
                <span className="text-sm font-medium">Projects</span>
              </div>
            </div>
            <p className="text-2xl font-bold mt-1">{projectCount}</p>
            <div className="flex flex-wrap gap-1.5 mt-1.5">
              {Object.entries(stateCounts).map(([state, count]) => (
                <span key={state} className="text-[10px] text-muted-foreground">
                  {String(count)} {state.toLowerCase().replace('_', ' ')}
                </span>
              ))}
            </div>
          </CardContent>
        </Card>

        {/* Jury (with inline group selector) */}
        <Card>
          <CardContent className="pt-4 pb-3">
            <div className="flex items-center gap-2 mb-1" data-jury-select>
              <Users className="h-4 w-4 text-purple-500" />
              <span className="text-sm font-medium">Jury</span>
            </div>
            {juryGroups && juryGroups.length > 0 ? (
              <Select
                value={round.juryGroupId ?? '__none__'}
                onValueChange={(value) => {
                  assignJuryMutation.mutate({
                    id: roundId,
                    juryGroupId: value === '__none__' ? null : value,
                  })
                }}
                disabled={assignJuryMutation.isPending}
              >
                <SelectTrigger className="h-8 text-xs mt-1">
                  <SelectValue placeholder="Select jury group..." />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="__none__">No jury assigned</SelectItem>
                  {juryGroups.map((jg: any) => (
                    <SelectItem key={jg.id} value={jg.id}>
                      {jg.name} ({jg._count?.members ?? 0} members)
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            ) : juryGroup ? (
              <>
                <p className="text-2xl font-bold mt-1">{juryMemberCount}</p>
                <p className="text-xs text-muted-foreground truncate">{juryGroup.name}</p>
              </>
            ) : (
              <>
                <p className="text-2xl font-bold mt-1 text-muted-foreground">&mdash;</p>
                <p className="text-xs text-muted-foreground">No jury groups yet</p>
              </>
            )}
          </CardContent>
        </Card>

        {/* Window */}
        <Card>
          <CardContent className="pt-4 pb-3">
            <div className="flex items-center gap-2">
              <CalendarDays className="h-4 w-4 text-emerald-500" />
              <span className="text-sm font-medium">Window</span>
            </div>
            {round.windowOpenAt || round.windowCloseAt ? (
              <>
                <p className="text-sm font-bold mt-1">
                  {round.windowOpenAt
                    ? new Date(round.windowOpenAt).toLocaleDateString()
                    : 'No start'}
                </p>
                <p className="text-xs text-muted-foreground">
                  {round.windowCloseAt
                    ? `Closes ${new Date(round.windowCloseAt).toLocaleDateString()}`
                    : 'No deadline'}
                </p>
              </>
            ) : (
              <>
                <p className="text-2xl font-bold mt-1 text-muted-foreground">&mdash;</p>
                <p className="text-xs text-muted-foreground">No dates set</p>
              </>
            )}
          </CardContent>
        </Card>

        {/* Advancement */}
        <Card>
          <CardContent className="pt-4 pb-3">
            <div className="flex items-center gap-2">
              <BarChart3 className="h-4 w-4 text-amber-500" />
              <span className="text-sm font-medium">Advancement</span>
            </div>
            {round.advancementRules && round.advancementRules.length > 0 ? (
              <>
                <p className="text-2xl font-bold mt-1">{round.advancementRules.length}</p>
                <p className="text-xs text-muted-foreground">
                  {round.advancementRules.map((r: any) => r.ruleType.replace('_', ' ').toLowerCase()).join(', ')}
                </p>
              </>
            ) : (
              <>
                <p className="text-2xl font-bold mt-1 text-muted-foreground">&mdash;</p>
                <p className="text-xs text-muted-foreground">Admin selection</p>
              </>
            )}
          </CardContent>
        </Card>
      </div>

      {/* ===== TABS ===== */}
      <Tabs value={activeTab} onValueChange={setActiveTab} className="space-y-4">
        <TabsList className="w-full sm:w-auto overflow-x-auto">
          <TabsTrigger value="overview">
            <Zap className="h-3.5 w-3.5 mr-1.5" />
            Overview
          </TabsTrigger>
          <TabsTrigger value="projects">
            <Layers className="h-3.5 w-3.5 mr-1.5" />
            Projects
          </TabsTrigger>
          {isFiltering && (
            <TabsTrigger value="filtering">
              <Shield className="h-3.5 w-3.5 mr-1.5" />
              Filtering
            </TabsTrigger>
          )}
          {isEvaluation && (
            <TabsTrigger value="assignments">
              <ClipboardList className="h-3.5 w-3.5 mr-1.5" />
              Assignments
            </TabsTrigger>
          )}
          <TabsTrigger value="config">
            <Settings className="h-3.5 w-3.5 mr-1.5" />
            Config
          </TabsTrigger>
          <TabsTrigger value="windows">
            <Clock className="h-3.5 w-3.5 mr-1.5" />
            Submissions
          </TabsTrigger>
          <TabsTrigger value="awards">
            <Trophy className="h-3.5 w-3.5 mr-1.5" />
            Awards
            {roundAwards.length > 0 && (
              <Badge variant="secondary" className="ml-1.5 h-5 min-w-5 text-[10px] px-1.5 bg-[#de0f1e] text-white">
                {roundAwards.length}
              </Badge>
            )}
          </TabsTrigger>
        </TabsList>

        {/* ═══════════ OVERVIEW TAB ═══════════ */}
        <TabsContent value="overview" className="space-y-6">
          {/* Readiness Checklist */}
          <Card>
            <CardHeader>
              <div className="flex items-center justify-between">
                <div>
                  <CardTitle className="text-base">Readiness Checklist</CardTitle>
                  <CardDescription>
                    {readyCount}/{readinessItems.length} items ready
                  </CardDescription>
                </div>
                <Badge
                  variant={readyCount === readinessItems.length ? 'default' : 'secondary'}
                  className={cn(
                    'text-xs',
                    readyCount === readinessItems.length
                      ? 'bg-emerald-100 text-emerald-700'
                      : 'bg-amber-100 text-amber-700',
                  )}
                >
                  {readyCount === readinessItems.length ? 'Ready' : 'Incomplete'}
                </Badge>
              </div>
            </CardHeader>
            <CardContent>
              <div className="space-y-3">
                {readinessItems.map((item) => (
                  <div key={item.label} className="flex items-start gap-3">
                    {item.ready ? (
                      <CheckCircle2 className="h-4 w-4 text-emerald-500 mt-0.5 shrink-0" />
                    ) : (
                      <AlertTriangle className="h-4 w-4 text-amber-500 mt-0.5 shrink-0" />
                    )}
                    <div className="flex-1 min-w-0">
                      <p className={cn('text-sm font-medium', item.ready && 'text-muted-foreground')}>
                        {item.label}
                      </p>
                      <p className="text-xs text-muted-foreground">{item.detail}</p>
                    </div>
                    {item.action && (
                      <Link href={item.action}>
                        <Button variant="outline" size="sm" className="shrink-0 text-xs">
                          {item.actionLabel}
                        </Button>
                      </Link>
                    )}
                  </div>
                ))}
              </div>
            </CardContent>
          </Card>

          {/* Quick Actions */}
          <Card>
            <CardHeader>
              <CardTitle className="text-base">Quick Actions</CardTitle>
              <CardDescription>Common operations for this round</CardDescription>
            </CardHeader>
            <CardContent>
              <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
                {/* Status transitions */}
                {status === 'ROUND_DRAFT' && (
                  <AlertDialog>
                    <AlertDialogTrigger asChild>
                      <button className="flex items-start gap-3 p-4 rounded-lg border hover:bg-muted/50 transition-colors text-left">
                        <Play className="h-5 w-5 text-emerald-600 mt-0.5 shrink-0" />
                        <div>
                          <p className="text-sm font-medium">Activate Round</p>
                          <p className="text-xs text-muted-foreground mt-0.5">
                            Start this round and allow project processing
                          </p>
                        </div>
                      </button>
                    </AlertDialogTrigger>
                    <AlertDialogContent>
                      <AlertDialogHeader>
                        <AlertDialogTitle>Activate this round?</AlertDialogTitle>
                        <AlertDialogDescription>
                          The round will go live. Projects can be processed and jury members will be able to see their assignments.
                        </AlertDialogDescription>
                      </AlertDialogHeader>
                      <AlertDialogFooter>
                        <AlertDialogCancel>Cancel</AlertDialogCancel>
                        <AlertDialogAction onClick={() => activateMutation.mutate({ roundId })}>
                          Activate
                        </AlertDialogAction>
                      </AlertDialogFooter>
                    </AlertDialogContent>
                  </AlertDialog>
                )}

                {status === 'ROUND_ACTIVE' && (
                  <AlertDialog>
                    <AlertDialogTrigger asChild>
                      <button className="flex items-start gap-3 p-4 rounded-lg border hover:bg-muted/50 transition-colors text-left">
                        <Square className="h-5 w-5 text-blue-600 mt-0.5 shrink-0" />
                        <div>
                          <p className="text-sm font-medium">Close Round</p>
                          <p className="text-xs text-muted-foreground mt-0.5">
                            Stop accepting changes and finalize results
                          </p>
                        </div>
                      </button>
                    </AlertDialogTrigger>
                    <AlertDialogContent>
                      <AlertDialogHeader>
                        <AlertDialogTitle>Close this round?</AlertDialogTitle>
                        <AlertDialogDescription>
                          No further changes will be accepted. You can reactivate later if needed.
                          {projectCount > 0 && (
                            <span className="block mt-2">
                              {projectCount} projects are currently in this round.
                            </span>
                          )}
                        </AlertDialogDescription>
                      </AlertDialogHeader>
                      <AlertDialogFooter>
                        <AlertDialogCancel>Cancel</AlertDialogCancel>
                        <AlertDialogAction onClick={() => closeMutation.mutate({ roundId })}>
                          Close Round
                        </AlertDialogAction>
                      </AlertDialogFooter>
                    </AlertDialogContent>
                  </AlertDialog>
                )}

                {/* Assign projects */}
                <Link href={poolLink}>
                  <button className="flex items-start gap-3 p-4 rounded-lg border hover:bg-muted/50 transition-colors text-left w-full">
                    <Layers className="h-5 w-5 text-blue-600 mt-0.5 shrink-0" />
                    <div>
                      <p className="text-sm font-medium">Assign Projects</p>
                      <p className="text-xs text-muted-foreground mt-0.5">
                        Add projects from the pool to this round
                      </p>
                    </div>
                  </button>
                </Link>

                {/* Filtering specific */}
                {isFiltering && (
                  <button
                    onClick={() => setActiveTab('filtering')}
                    className="flex items-start gap-3 p-4 rounded-lg border hover:bg-muted/50 transition-colors text-left"
                  >
                    <Shield className="h-5 w-5 text-amber-600 mt-0.5 shrink-0" />
                    <div>
                      <p className="text-sm font-medium">Run AI Filtering</p>
                      <p className="text-xs text-muted-foreground mt-0.5">
                        Screen projects with AI and manual review
                      </p>
                    </div>
                  </button>
                )}

                {/* Jury assignment for evaluation/filtering */}
                {(isEvaluation || isFiltering) && !juryGroup && (
                  <button
                    onClick={() => {
                      const el = document.querySelector('[data-jury-select]')
                      if (el) el.scrollIntoView({ behavior: 'smooth', block: 'center' })
                    }}
                    className="flex items-start gap-3 p-4 rounded-lg border hover:bg-muted/50 transition-colors text-left border-amber-200 bg-amber-50/50"
                  >
                    <UserPlus className="h-5 w-5 text-amber-600 mt-0.5 shrink-0" />
                    <div>
                      <p className="text-sm font-medium">Assign Jury Group</p>
                      <p className="text-xs text-muted-foreground mt-0.5">
                        No jury group assigned. Select one in the Jury card above.
                      </p>
                    </div>
                  </button>
                )}

                {/* Evaluation: manage assignments */}
                {isEvaluation && (
                  <button
                    onClick={() => setActiveTab('assignments')}
                    className="flex items-start gap-3 p-4 rounded-lg border hover:bg-muted/50 transition-colors text-left"
                  >
                    <ClipboardList className="h-5 w-5 text-blue-600 mt-0.5 shrink-0" />
                    <div>
                      <p className="text-sm font-medium">Manage Assignments</p>
                      <p className="text-xs text-muted-foreground mt-0.5">
                        Generate and review jury-project assignments
                      </p>
                    </div>
                  </button>
                )}

                {/* View projects */}
                <button
                  onClick={() => setActiveTab('projects')}
                  className="flex items-start gap-3 p-4 rounded-lg border hover:bg-muted/50 transition-colors text-left"
                >
                  <BarChart3 className="h-5 w-5 text-purple-600 mt-0.5 shrink-0" />
                  <div>
                    <p className="text-sm font-medium">Manage Projects</p>
                    <p className="text-xs text-muted-foreground mt-0.5">
                      View, filter, and transition project states
                    </p>
                  </div>
                </button>

                {/* Advance projects (shown when PASSED > 0) */}
                {passedCount > 0 && (
                  <button
                    onClick={() => setAdvanceDialogOpen(true)}
                    className="flex items-start gap-3 p-4 rounded-lg border hover:bg-muted/50 transition-colors text-left border-green-200 bg-green-50/50"
                  >
                    <ArrowRight className="h-5 w-5 text-green-600 mt-0.5 shrink-0" />
                    <div>
                      <p className="text-sm font-medium">Advance Projects</p>
                      <p className="text-xs text-muted-foreground mt-0.5">
                        Move {passedCount} passed project(s) to the next round
                      </p>
                    </div>
                  </button>
                )}
              </div>
            </CardContent>
          </Card>

          {/* Advance Projects Confirmation Dialog */}
          <AlertDialog open={advanceDialogOpen} onOpenChange={setAdvanceDialogOpen}>
            <AlertDialogContent>
              <AlertDialogHeader>
                <AlertDialogTitle>Advance {passedCount} project(s)?</AlertDialogTitle>
                <AlertDialogDescription>
                  All projects with PASSED status in this round will be moved to the next round.
                  This action creates new entries in the next round and marks current entries as completed.
                </AlertDialogDescription>
              </AlertDialogHeader>
              <AlertDialogFooter>
                <AlertDialogCancel>Cancel</AlertDialogCancel>
                <AlertDialogAction
                  onClick={() => advanceMutation.mutate({ roundId })}
                  disabled={advanceMutation.isPending}
                >
                  {advanceMutation.isPending && <Loader2 className="h-4 w-4 mr-1.5 animate-spin" />}
                  Advance Projects
                </AlertDialogAction>
              </AlertDialogFooter>
            </AlertDialogContent>
          </AlertDialog>

          {/* Round Info + Project Breakdown */}
          <div className="grid gap-4 sm:grid-cols-2">
            <Card>
              <CardHeader>
                <CardTitle className="text-sm">Round Details</CardTitle>
              </CardHeader>
              <CardContent className="space-y-3 text-sm">
                <div className="flex justify-between">
                  <span className="text-muted-foreground">Type</span>
                  <Badge variant="secondary" className={cn('text-xs', typeCfg.color)}>{typeCfg.label}</Badge>
                </div>
                <div className="flex justify-between">
                  <span className="text-muted-foreground">Status</span>
                  <span className="font-medium">{statusCfg.label}</span>
                </div>
                <div className="flex justify-between">
                  <span className="text-muted-foreground">Sort Order</span>
                  <span className="font-medium font-mono">{round.sortOrder}</span>
                </div>
                {round.purposeKey && (
                  <div className="flex justify-between">
                    <span className="text-muted-foreground">Purpose</span>
                    <span className="font-medium">{round.purposeKey}</span>
                  </div>
                )}
                <div className="flex justify-between">
                  <span className="text-muted-foreground">Jury Group</span>
                  <span className="font-medium">
                    {juryGroup ? juryGroup.name : '\u2014'}
                  </span>
                </div>
                <div className="flex justify-between">
                  <span className="text-muted-foreground">Opens</span>
                  <span className="font-medium">
                    {round.windowOpenAt ? new Date(round.windowOpenAt).toLocaleString() : '\u2014'}
                  </span>
                </div>
                <div className="flex justify-between">
                  <span className="text-muted-foreground">Closes</span>
                  <span className="font-medium">
                    {round.windowCloseAt ? new Date(round.windowCloseAt).toLocaleString() : '\u2014'}
                  </span>
                </div>
              </CardContent>
            </Card>

            <Card>
              <CardHeader>
                <CardTitle className="text-sm">Project Breakdown</CardTitle>
              </CardHeader>
              <CardContent>
                {projectCount === 0 ? (
                  <p className="text-sm text-muted-foreground py-4 text-center">
                    No projects assigned yet
                  </p>
                ) : (
                  <div className="space-y-2">
                    {['PENDING', 'IN_PROGRESS', 'PASSED', 'REJECTED', 'COMPLETED', 'WITHDRAWN'].map((state) => {
                      const count = stateCounts[state] || 0
                      if (count === 0) return null
                      const pct = ((count / projectCount) * 100).toFixed(0)
                      return (
                        <div key={state}>
                          <div className="flex justify-between text-xs mb-1">
                            <span className="text-muted-foreground capitalize">{state.toLowerCase().replace('_', ' ')}</span>
                            <span className="font-medium">{count} ({pct}%)</span>
                          </div>
                          <div className="h-1.5 bg-muted rounded-full overflow-hidden">
                            <div
                              className={cn('h-full rounded-full transition-all', stateColors[state])}
                              style={{ width: `${pct}%` }}
                            />
                          </div>
                        </div>
                      )
                    })}
                  </div>
                )}
              </CardContent>
            </Card>
          </div>
        </TabsContent>

        {/* ═══════════ PROJECTS TAB ═══════════ */}
        <TabsContent value="projects" className="space-y-4">
          <ProjectStatesTable competitionId={competitionId} roundId={roundId} />
        </TabsContent>

        {/* ═══════════ FILTERING TAB ═══════════ */}
        {isFiltering && (
          <TabsContent value="filtering" className="space-y-4">
            <FilteringDashboard competitionId={competitionId} roundId={roundId} />
          </TabsContent>
        )}

        {/* ═══════════ ASSIGNMENTS TAB (Evaluation rounds) ═══════════ */}
        {isEvaluation && (
          <TabsContent value="assignments" className="space-y-6">
            {/* Coverage Report */}
            <CoverageReport roundId={roundId} />

            {/* Generate Assignments */}
            <Card>
              <CardHeader>
                <div className="flex items-center justify-between">
                  <div>
                    <CardTitle className="text-base">Assignment Generation</CardTitle>
                    <CardDescription>
                      AI-suggested jury-to-project assignments based on expertise and workload
                    </CardDescription>
                  </div>
                  <Button
                    size="sm"
                    onClick={() => setPreviewSheetOpen(true)}
                    disabled={projectCount === 0 || !juryGroup}
                  >
                    <Zap className="h-4 w-4 mr-1.5" />
                    Generate Assignments
                  </Button>
                </div>
              </CardHeader>
              <CardContent>
                {!juryGroup && (
                  <div className="flex items-center gap-2 p-3 rounded-lg bg-amber-50 border border-amber-200 text-sm text-amber-800">
                    <AlertTriangle className="h-4 w-4 shrink-0" />
                    Assign a jury group first before generating assignments.
                  </div>
                )}
                {projectCount === 0 && (
                  <div className="flex items-center gap-2 p-3 rounded-lg bg-amber-50 border border-amber-200 text-sm text-amber-800">
                    <AlertTriangle className="h-4 w-4 shrink-0" />
                    Add projects to this round first.
                  </div>
                )}
                {juryGroup && projectCount > 0 && (
                  <p className="text-sm text-muted-foreground">
                    Click &quot;Generate Assignments&quot; to preview AI-suggested assignments.
                    You can review and execute them from the preview sheet.
                  </p>
                )}
              </CardContent>
            </Card>

            {/* Jury Progress + Score Distribution */}
            <div className="grid gap-4 lg:grid-cols-2">
              <JuryProgressTable roundId={roundId} />
              <ScoreDistribution roundId={roundId} />
            </div>

            {/* Actions: Send Reminders + Export */}
            <div className="flex flex-wrap items-center gap-3">
              <SendRemindersButton roundId={roundId} />
              <Button variant="outline" size="sm" onClick={() => setExportOpen(true)}>
                <Download className="h-4 w-4 mr-1.5" />
                Export Evaluations
              </Button>
            </div>

            {/* Individual Assignments Table */}
            <IndividualAssignmentsTable roundId={roundId} />

            {/* Unassigned Queue */}
            <RoundUnassignedQueue roundId={roundId} />

            {/* Assignment Preview Sheet */}
            <AssignmentPreviewSheet
              roundId={roundId}
              open={previewSheetOpen}
              onOpenChange={setPreviewSheetOpen}
            />

            {/* CSV Export Dialog */}
            <ExportEvaluationsDialog roundId={roundId} open={exportOpen} onOpenChange={setExportOpen} />
          </TabsContent>
        )}

        {/* ═══════════ CONFIG TAB ═══════════ */}
        <TabsContent value="config" className="space-y-6">
          {/* General Round Settings */}
          <Card>
            <CardHeader>
              <CardTitle className="text-base">General Settings</CardTitle>
              <CardDescription>Settings that apply to this round regardless of type</CardDescription>
            </CardHeader>
            <CardContent className="space-y-4">
              <div className="flex items-center justify-between">
                <div className="space-y-0.5">
                  <Label htmlFor="notify-on-entry" className="text-sm font-medium">
                    Notify on round entry
                  </Label>
                  <p className="text-xs text-muted-foreground">
                    Send an automated email to project applicants when their project enters this round
                  </p>
                </div>
                <Switch
                  id="notify-on-entry"
                  checked={!!config.notifyOnEntry}
                  onCheckedChange={(checked) => {
                    handleConfigChange({ ...config, notifyOnEntry: checked })
                  }}
                />
              </div>
            </CardContent>
          </Card>

          {/* Round-type-specific config */}
          <RoundConfigForm
            roundType={round.roundType}
            config={config}
            onChange={handleConfigChange}
            juryGroups={juryGroups?.map((jg: any) => ({ id: jg.id, name: jg.name }))}
          />

          {/* Evaluation Criteria Editor (EVALUATION rounds only) */}
          {isEvaluation && <EvaluationCriteriaEditor roundId={roundId} />}

          {/* Document Requirements */}
          <Card>
            <CardHeader>
              <CardTitle className="text-base">Document Requirements</CardTitle>
              <CardDescription>
                Files applicants must submit for this round
                {round.windowCloseAt && (
                  <> &mdash; due by {new Date(round.windowCloseAt).toLocaleDateString()}</>
                )}
              </CardDescription>
            </CardHeader>
            <CardContent>
              <FileRequirementsEditor
                roundId={roundId}
                windowOpenAt={round.windowOpenAt}
                windowCloseAt={round.windowCloseAt}
              />
            </CardContent>
          </Card>
        </TabsContent>

        {/* ═══════════ SUBMISSION WINDOWS TAB ═══════════ */}
        <TabsContent value="windows" className="space-y-4">
          <SubmissionWindowManager competitionId={competitionId} roundId={roundId} />
        </TabsContent>

        {/* ═══════════ AWARDS TAB ═══════════ */}
        <TabsContent value="awards" className="space-y-4">
          <Card>
            <CardContent className="p-6">
              {roundAwards.length === 0 ? (
                <div className="text-center py-8 text-muted-foreground">
                  <Trophy className="h-8 w-8 mx-auto mb-2 opacity-40" />
                  <p className="text-sm">No awards linked to this round</p>
                  <p className="text-xs mt-1">
                    Create an award and set this round as its evaluation round to see it here
                  </p>
                </div>
              ) : (
                <div className="space-y-3">
                  {roundAwards.map((award) => {
                    const eligibleCount = award._count?.eligibilities || 0
                    const autoTagRules = award.autoTagRulesJson as { rules?: unknown[] } | null
                    const ruleCount = autoTagRules?.rules?.length || 0

                    return (
                      <Link
                        key={award.id}
                        href={`/admin/awards/${award.id}` as Route}
                        className="block"
                      >
                        <div className="flex items-start justify-between gap-4 rounded-lg border p-4 transition-all hover:bg-muted/50 hover:shadow-sm">
                          <div className="flex-1 min-w-0">
                            <div className="flex items-center gap-2 mb-1">
                              <h3 className="font-medium truncate">{award.name}</h3>
                              <Badge
                                variant={
                                  award.eligibilityMode === 'SEPARATE_POOL'
                                    ? 'default'
                                    : 'secondary'
                                }
                                className="shrink-0"
                              >
                                {award.eligibilityMode === 'SEPARATE_POOL'
                                  ? 'Separate Pool'
                                  : 'Stay in Main'}
                              </Badge>
                            </div>
                            {award.description && (
                              <p className="text-sm text-muted-foreground line-clamp-1">
                                {award.description}
                              </p>
                            )}
                          </div>
                          <div className="flex items-center gap-4 text-sm text-muted-foreground shrink-0">
                            <div className="text-right">
                              <div className="font-medium text-foreground">{ruleCount}</div>
                              <div className="text-xs">{ruleCount === 1 ? 'rule' : 'rules'}</div>
                            </div>
                            <div className="text-right">
                              <div className="font-medium text-foreground">{eligibleCount}</div>
                              <div className="text-xs">eligible</div>
                            </div>
                          </div>
                        </div>
                      </Link>
                    )
                  })}
                </div>
              )}
            </CardContent>
          </Card>
        </TabsContent>
      </Tabs>
    </div>
  )
}

// ═══════════════════════════════════════════════════════════════════════════
// Sub-components
// ═══════════════════════════════════════════════════════════════════════════

// ── Unassigned projects queue ────────────────────────────────────────────

function RoundUnassignedQueue({ roundId }: { roundId: string }) {
  const { data: unassigned, isLoading } = trpc.roundAssignment.unassignedQueue.useQuery(
    { roundId, requiredReviews: 3 },
    { refetchInterval: 15_000 },
  )

  return (
    <Card>
      <CardHeader>
        <CardTitle className="text-base">Unassigned Projects</CardTitle>
        <CardDescription>Projects with fewer than 3 jury assignments</CardDescription>
      </CardHeader>
      <CardContent>
        {isLoading ? (
          <div className="space-y-2">
            {[1, 2, 3].map((i) => <Skeleton key={i} className="h-14 w-full" />)}
          </div>
        ) : unassigned && unassigned.length > 0 ? (
          <div className="space-y-2 max-h-[400px] overflow-y-auto">
            {unassigned.map((project: any) => (
              <div
                key={project.id}
                className="flex justify-between items-center p-3 border rounded-md hover:bg-muted/30"
              >
                <div className="min-w-0">
                  <p className="text-sm font-medium truncate">{project.title}</p>
                  <p className="text-xs text-muted-foreground">
                    {project.competitionCategory || 'No category'}
                    {project.teamName && ` \u00b7 ${project.teamName}`}
                  </p>
                </div>
                <Badge variant="outline" className={cn(
                  'text-xs shrink-0 ml-3',
                  (project.assignmentCount || 0) === 0
                    ? 'bg-red-50 text-red-700 border-red-200'
                    : 'bg-amber-50 text-amber-700 border-amber-200',
                )}>
                  {project.assignmentCount || 0} / 3
                </Badge>
              </div>
            ))}
          </div>
        ) : (
          <p className="text-sm text-muted-foreground text-center py-6">
            All projects have sufficient assignments
          </p>
        )}
      </CardContent>
    </Card>
  )
}

// ── Jury Progress Table ──────────────────────────────────────────────────

function JuryProgressTable({ roundId }: { roundId: string }) {
  const { data: workload, isLoading } = trpc.analytics.getJurorWorkload.useQuery(
    { roundId },
    { refetchInterval: 15_000 },
  )

  return (
    <Card>
      <CardHeader>
        <CardTitle className="text-base">Jury Progress</CardTitle>
        <CardDescription>Evaluation completion per juror</CardDescription>
      </CardHeader>
      <CardContent>
        {isLoading ? (
          <div className="space-y-3">
            {[1, 2, 3].map((i) => <Skeleton key={i} className="h-10 w-full" />)}
          </div>
        ) : !workload || workload.length === 0 ? (
          <p className="text-sm text-muted-foreground text-center py-6">
            No assignments yet
          </p>
        ) : (
          <div className="space-y-3 max-h-[350px] overflow-y-auto">
            {workload.map((juror) => {
              const pct = juror.completionRate
              const barColor = pct === 100
                ? 'bg-emerald-500'
                : pct >= 50
                  ? 'bg-blue-500'
                  : pct > 0
                    ? 'bg-amber-500'
                    : 'bg-gray-300'

              return (
                <div key={juror.id} className="space-y-1">
                  <div className="flex justify-between text-xs">
                    <span className="font-medium truncate max-w-[60%]">{juror.name}</span>
                    <span className="text-muted-foreground shrink-0">
                      {juror.completed}/{juror.assigned} ({pct}%)
                    </span>
                  </div>
                  <div className="h-1.5 bg-muted rounded-full overflow-hidden">
                    <div
                      className={cn('h-full rounded-full transition-all', barColor)}
                      style={{ width: `${pct}%` }}
                    />
                  </div>
                </div>
              )
            })}
          </div>
        )}
      </CardContent>
    </Card>
  )
}

// ── Score Distribution ───────────────────────────────────────────────────

function ScoreDistribution({ roundId }: { roundId: string }) {
  const { data: dist, isLoading } = trpc.analytics.getRoundScoreDistribution.useQuery(
    { roundId },
    { refetchInterval: 15_000 },
  )

  const maxCount = useMemo(() =>
    dist ? Math.max(...dist.globalDistribution.map((b) => b.count), 1) : 1,
  [dist])

  return (
    <Card>
      <CardHeader>
        <CardTitle className="text-base">Score Distribution</CardTitle>
        <CardDescription>
          {dist ? `${dist.totalEvaluations} evaluations \u2014 avg ${dist.averageGlobalScore.toFixed(1)}` : 'Loading...'}
        </CardDescription>
      </CardHeader>
      <CardContent>
        {isLoading ? (
          <div className="flex items-end gap-1 h-32">
            {Array.from({ length: 10 }).map((_, i) => <Skeleton key={i} className="flex-1 h-full" />)}
          </div>
        ) : !dist || dist.totalEvaluations === 0 ? (
          <p className="text-sm text-muted-foreground text-center py-6">
            No evaluations submitted yet
          </p>
        ) : (
          <div className="flex items-end gap-1 h-32">
            {dist.globalDistribution.map((bucket) => {
              const heightPct = (bucket.count / maxCount) * 100
              return (
                <div key={bucket.score} className="flex-1 flex flex-col items-center gap-1">
                  <span className="text-[9px] text-muted-foreground">{bucket.count || ''}</span>
                  <div className="w-full relative rounded-t" style={{ height: `${Math.max(heightPct, 2)}%` }}>
                    <div className={cn(
                      'absolute inset-0 rounded-t transition-all',
                      bucket.score <= 3 ? 'bg-red-400' :
                      bucket.score <= 6 ? 'bg-amber-400' :
                      'bg-emerald-400',
                    )} />
                  </div>
                  <span className="text-[10px] text-muted-foreground">{bucket.score}</span>
                </div>
              )
            })}
          </div>
        )}
      </CardContent>
    </Card>
  )
}

// ── Send Reminders Button ────────────────────────────────────────────────

function SendRemindersButton({ roundId }: { roundId: string }) {
  const [open, setOpen] = useState(false)
  const mutation = trpc.evaluation.triggerReminders.useMutation({
    onSuccess: (data) => {
      toast.success(`Sent ${data.sent} reminder(s)`)
      setOpen(false)
    },
    onError: (err) => toast.error(err.message),
  })

  return (
    <>
      <Button variant="outline" size="sm" onClick={() => setOpen(true)}>
        <Send className="h-4 w-4 mr-1.5" />
        Send Reminders
      </Button>
      <AlertDialog open={open} onOpenChange={setOpen}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>Send evaluation reminders?</AlertDialogTitle>
            <AlertDialogDescription>
              This will send reminder emails to all jurors who have incomplete evaluations for this round.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel>Cancel</AlertDialogCancel>
            <AlertDialogAction
              onClick={() => mutation.mutate({ roundId })}
              disabled={mutation.isPending}
            >
              {mutation.isPending && <Loader2 className="h-4 w-4 mr-1.5 animate-spin" />}
              Send Reminders
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </>
  )
}

// ── Export Evaluations Dialog ─────────────────────────────────────────────

function ExportEvaluationsDialog({
  roundId,
  open,
  onOpenChange,
}: {
  roundId: string
  open: boolean
  onOpenChange: (open: boolean) => void
}) {
  const [exportData, setExportData] = useState<any>(undefined)
  const [isLoadingExport, setIsLoadingExport] = useState(false)
  const utils = trpc.useUtils()

  const handleRequestData = async () => {
    setIsLoadingExport(true)
    try {
      const data = await utils.export.evaluations.fetch({ roundId, includeDetails: true })
      setExportData(data)
      return data
    } finally {
      setIsLoadingExport(false)
    }
  }

  return (
    <CsvExportDialog
      open={open}
      onOpenChange={onOpenChange}
      exportData={exportData}
      isLoading={isLoadingExport}
      filename={`evaluations-${roundId}`}
      onRequestData={handleRequestData}
    />
  )
}

// ── Individual Assignments Table ─────────────────────────────────────────

function IndividualAssignmentsTable({ roundId }: { roundId: string }) {
  const [addDialogOpen, setAddDialogOpen] = useState(false)
  const [newUserId, setNewUserId] = useState('')
  const [newProjectId, setNewProjectId] = useState('')

  const utils = trpc.useUtils()
  const { data: assignments, isLoading } = trpc.assignment.listByStage.useQuery(
    { roundId },
    { refetchInterval: 15_000 },
  )

  const deleteMutation = trpc.assignment.delete.useMutation({
    onSuccess: () => {
      utils.assignment.listByStage.invalidate({ roundId })
      toast.success('Assignment removed')
    },
    onError: (err) => toast.error(err.message),
  })

  const createMutation = trpc.assignment.create.useMutation({
    onSuccess: () => {
      utils.assignment.listByStage.invalidate({ roundId })
      toast.success('Assignment created')
      setAddDialogOpen(false)
      setNewUserId('')
      setNewProjectId('')
    },
    onError: (err) => toast.error(err.message),
  })

  return (
    <Card>
      <CardHeader>
        <div className="flex items-center justify-between">
          <div>
            <CardTitle className="text-base">All Assignments</CardTitle>
            <CardDescription>
              {assignments?.length ?? 0} individual jury-project assignments
            </CardDescription>
          </div>
          <Button size="sm" variant="outline" onClick={() => setAddDialogOpen(true)}>
            <Plus className="h-4 w-4 mr-1.5" />
            Add
          </Button>
        </div>
      </CardHeader>
      <CardContent>
        {isLoading ? (
          <div className="space-y-2">
            {[1, 2, 3, 4, 5].map((i) => <Skeleton key={i} className="h-12 w-full" />)}
          </div>
        ) : !assignments || assignments.length === 0 ? (
          <p className="text-sm text-muted-foreground text-center py-6">
            No assignments yet. Generate assignments or add one manually.
          </p>
        ) : (
          <div className="space-y-1 max-h-[500px] overflow-y-auto">
            <div className="grid grid-cols-[1fr_1fr_100px_60px] gap-2 text-xs text-muted-foreground font-medium px-3 py-2 sticky top-0 bg-background border-b">
              <span>Juror</span>
              <span>Project</span>
              <span>Status</span>
              <span />
            </div>
            {assignments.map((a: any) => (
              <div
                key={a.id}
                className="grid grid-cols-[1fr_1fr_100px_60px] gap-2 items-center px-3 py-2 rounded-md hover:bg-muted/30 text-sm"
              >
                <span className="truncate">{a.user?.name || a.user?.email || 'Unknown'}</span>
                <span className="truncate text-muted-foreground">{a.project?.title || 'Unknown'}</span>
                <Badge
                  variant="outline"
                  className={cn(
                    'text-[10px] justify-center',
                    a.evaluation?.status === 'SUBMITTED'
                      ? 'bg-emerald-50 text-emerald-700 border-emerald-200'
                      : a.evaluation?.status === 'IN_PROGRESS'
                        ? 'bg-blue-50 text-blue-700 border-blue-200'
                        : 'bg-gray-50 text-gray-600 border-gray-200',
                  )}
                >
                  {a.evaluation?.status || 'PENDING'}
                </Badge>
                <Button
                  variant="ghost"
                  size="icon"
                  className="h-7 w-7"
                  onClick={() => deleteMutation.mutate({ id: a.id })}
                  disabled={deleteMutation.isPending}
                >
                  <Trash2 className="h-3.5 w-3.5 text-muted-foreground hover:text-red-500" />
                </Button>
              </div>
            ))}
          </div>
        )}
      </CardContent>

      {/* Add Assignment Dialog */}
      <Dialog open={addDialogOpen} onOpenChange={setAddDialogOpen}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Add Assignment</DialogTitle>
            <DialogDescription>
              Manually assign a juror to evaluate a project
            </DialogDescription>
          </DialogHeader>
          <div className="space-y-4">
            <div className="space-y-2">
              <Label className="text-sm">Juror User ID</Label>
              <Input
                placeholder="Enter jury member user ID..."
                value={newUserId}
                onChange={(e) => setNewUserId(e.target.value)}
              />
            </div>
            <div className="space-y-2">
              <Label className="text-sm">Project ID</Label>
              <Input
                placeholder="Enter project ID..."
                value={newProjectId}
                onChange={(e) => setNewProjectId(e.target.value)}
              />
            </div>
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setAddDialogOpen(false)}>Cancel</Button>
            <Button
              onClick={() => createMutation.mutate({
                userId: newUserId,
                projectId: newProjectId,
                roundId,
              })}
              disabled={!newUserId || !newProjectId || createMutation.isPending}
            >
              {createMutation.isPending && <Loader2 className="h-4 w-4 mr-1.5 animate-spin" />}
              Create Assignment
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </Card>
  )
}

// ── Evaluation Criteria Editor ───────────────────────────────────────────

function EvaluationCriteriaEditor({ roundId }: { roundId: string }) {
  const [editing, setEditing] = useState(false)
  const [criteria, setCriteria] = useState<Array<{
    id: string; label: string; description?: string; weight?: number; minScore?: number; maxScore?: number
  }>>([])

  const utils = trpc.useUtils()
  const { data: form, isLoading } = trpc.evaluation.getForm.useQuery(
    { roundId },
    { refetchInterval: 30_000 },
  )

  const upsertMutation = trpc.evaluation.upsertForm.useMutation({
    onSuccess: () => {
      utils.evaluation.getForm.invalidate({ roundId })
      toast.success('Evaluation criteria saved')
      setEditing(false)
    },
    onError: (err) => toast.error(err.message),
  })

  // Sync from server
  if (form && !editing) {
    const serverCriteria = form.criteriaJson ?? []
    if (JSON.stringify(serverCriteria) !== JSON.stringify(criteria)) {
      setCriteria(serverCriteria)
    }
  }

  const handleAdd = () => {
    setCriteria([...criteria, {
      id: `c-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`,
      label: '',
      description: '',
      weight: 1,
      minScore: 0,
      maxScore: 10,
    }])
    setEditing(true)
  }

  const handleRemove = (id: string) => {
    setCriteria(criteria.filter((c) => c.id !== id))
  }

  const handleChange = (id: string, field: string, value: string | number) => {
    setCriteria(criteria.map((c) =>
      c.id === id ? { ...c, [field]: value } : c,
    ))
    setEditing(true)
  }

  const handleSave = () => {
    const validCriteria = criteria.filter((c) => c.label.trim())
    if (validCriteria.length === 0) {
      toast.error('Add at least one criterion')
      return
    }
    upsertMutation.mutate({ roundId, criteria: validCriteria })
  }

  return (
    <Card>
      <CardHeader>
        <div className="flex items-center justify-between">
          <div>
            <CardTitle className="text-base">Evaluation Criteria</CardTitle>
            <CardDescription>
              {form ? `Version ${form.version} \u2014 ${form.criteriaJson.length} criteria` : 'No criteria defined yet'}
            </CardDescription>
          </div>
          <div className="flex items-center gap-2">
            {editing && (
              <Button size="sm" variant="outline" onClick={() => {
                setEditing(false)
                if (form) setCriteria(form.criteriaJson)
              }}>
                Cancel
              </Button>
            )}
            {editing ? (
              <Button size="sm" onClick={handleSave} disabled={upsertMutation.isPending}>
                {upsertMutation.isPending && <Loader2 className="h-4 w-4 mr-1.5 animate-spin" />}
                Save Criteria
              </Button>
            ) : (
              <Button size="sm" variant="outline" onClick={handleAdd}>
                <Plus className="h-4 w-4 mr-1.5" />
                Add Criterion
              </Button>
            )}
          </div>
        </div>
      </CardHeader>
      <CardContent>
        {isLoading ? (
          <div className="space-y-3">
            {[1, 2, 3].map((i) => <Skeleton key={i} className="h-16 w-full" />)}
          </div>
        ) : criteria.length === 0 ? (
          <div className="text-center py-6 text-muted-foreground">
            <FileText className="h-8 w-8 mx-auto mb-2 opacity-40" />
            <p className="text-sm">No evaluation criteria defined</p>
            <p className="text-xs mt-1">Add criteria that jurors will use to score projects</p>
          </div>
        ) : (
          <div className="space-y-3">
            {criteria.map((c, idx) => (
              <div key={c.id} className="flex gap-3 items-start p-3 border rounded-lg bg-muted/20">
                <span className="text-xs text-muted-foreground font-mono mt-2.5 shrink-0 w-5 text-center">
                  {idx + 1}
                </span>
                <div className="flex-1 space-y-2">
                  <Input
                    placeholder="Criterion label (e.g., Innovation)"
                    value={c.label}
                    onChange={(e) => handleChange(c.id, 'label', e.target.value)}
                    className="h-8 text-sm"
                  />
                  <Input
                    placeholder="Description (optional)"
                    value={c.description || ''}
                    onChange={(e) => handleChange(c.id, 'description', e.target.value)}
                    className="h-7 text-xs"
                  />
                  <div className="flex gap-2">
                    <div className="flex-1">
                      <Label className="text-[10px] text-muted-foreground">Weight</Label>
                      <Input
                        type="number"
                        min={0}
                        max={100}
                        value={c.weight ?? 1}
                        onChange={(e) => handleChange(c.id, 'weight', Number(e.target.value))}
                        className="h-7 text-xs"
                      />
                    </div>
                    <div className="flex-1">
                      <Label className="text-[10px] text-muted-foreground">Min Score</Label>
                      <Input
                        type="number"
                        min={0}
                        value={c.minScore ?? 0}
                        onChange={(e) => handleChange(c.id, 'minScore', Number(e.target.value))}
                        className="h-7 text-xs"
                      />
                    </div>
                    <div className="flex-1">
                      <Label className="text-[10px] text-muted-foreground">Max Score</Label>
                      <Input
                        type="number"
                        min={1}
                        value={c.maxScore ?? 10}
                        onChange={(e) => handleChange(c.id, 'maxScore', Number(e.target.value))}
                        className="h-7 text-xs"
                      />
                    </div>
                  </div>
                </div>
                <Button
                  variant="ghost"
                  size="icon"
                  className="h-7 w-7 mt-1 shrink-0"
                  onClick={() => { handleRemove(c.id); setEditing(true) }}
                >
                  <X className="h-3.5 w-3.5 text-muted-foreground hover:text-red-500" />
                </Button>
              </div>
            ))}
            {!editing && (
              <Button variant="outline" size="sm" className="w-full" onClick={handleAdd}>
                <Plus className="h-4 w-4 mr-1.5" />
                Add Criterion
              </Button>
            )}
          </div>
        )}
      </CardContent>
    </Card>
  )
}
