'use client'

import React, { useState, useEffect, useRef, useMemo } from 'react'
import { trpc } from '@/lib/trpc/client'
import { toast } from 'sonner'
import { cn } from '@/lib/utils'
import {
  DndContext,
  closestCenter,
  KeyboardSensor,
  PointerSensor,
  useSensor,
  useSensors,
  type DragEndEvent,
} from '@dnd-kit/core'
import {
  arrayMove,
  SortableContext,
  sortableKeyboardCoordinates,
  useSortable,
  verticalListSortingStrategy,
} from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
import { AnimatePresence, motion } from 'motion/react'
import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card'
import { Skeleton } from '@/components/ui/skeleton'
import {
  Sheet,
  SheetContent,
  SheetHeader,
  SheetTitle,
  SheetDescription,
} from '@/components/ui/sheet'
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import {
  GripVertical,
  BarChart3,
  Loader2,
  RefreshCw,
  Trophy,
  ExternalLink,
} from 'lucide-react'
import type { RankedProjectEntry } from '@/server/services/ai-ranking'

// ─── Types ────────────────────────────────────────────────────────────────────

type RankingDashboardProps = {
  competitionId: string
  roundId: string
}

type ProjectInfo = {
  title: string
  teamName: string | null
  country: string | null
}

type JurorScore = {
  jurorName: string
  globalScore: number | null
  decision: boolean | null
}

type SortableProjectRowProps = {
  projectId: string
  currentRank: number
  entry: RankedProjectEntry | undefined
  projectInfo: ProjectInfo | undefined
  jurorScores: JurorScore[] | undefined
  onSelect: () => void
  isSelected: boolean
}

// ─── Sub-component: SortableProjectRow ────────────────────────────────────────

function SortableProjectRow({
  projectId,
  currentRank,
  entry,
  projectInfo,
  jurorScores,
  onSelect,
  isSelected,
}: SortableProjectRowProps) {
  const {
    attributes,
    listeners,
    setNodeRef,
    transform,
    transition,
    isDragging,
  } = useSortable({ id: projectId })

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

  // isOverridden: current position differs from AI-assigned rank
  const isOverridden = entry !== undefined && currentRank !== entry.rank

  // Compute yes count from juror scores
  const yesCount = jurorScores?.filter((j) => j.decision === true).length ?? 0
  const totalJurors = jurorScores?.length ?? entry?.evaluatorCount ?? 0

  return (
    <div
      ref={setNodeRef}
      style={style}
      onClick={onSelect}
      className={cn(
        'flex items-center gap-3 rounded-lg border bg-card p-3 cursor-pointer transition-all hover:shadow-sm',
        isDragging && 'opacity-50 shadow-lg ring-2 ring-[#de0f1e]/30',
        isSelected && 'ring-2 ring-[#de0f1e]',
      )}
    >
      {/* Drag handle */}
      <button
        className="cursor-grab touch-none text-muted-foreground hover:text-foreground flex-shrink-0"
        onClick={(e) => e.stopPropagation()}
        {...attributes}
        {...listeners}
      >
        <GripVertical className="h-4 w-4" />
      </button>

      {/* Rank badge */}
      {isOverridden ? (
        <Badge className="flex-shrink-0 bg-amber-100 text-amber-700 hover:bg-amber-100 border-amber-200 text-xs font-semibold">
          #{currentRank} (override)
        </Badge>
      ) : (
        <Badge
          className="flex-shrink-0 text-xs font-semibold"
          style={{ backgroundColor: '#053d57', color: '#fefefe' }}
        >
          #{currentRank}
        </Badge>
      )}

      {/* Project info */}
      <div className="flex-1 min-w-0">
        <p className="text-sm font-medium truncate">
          {projectInfo?.title ?? `Project …${projectId.slice(-6)}`}
        </p>
        {projectInfo?.teamName && (
          <p className="text-xs text-muted-foreground truncate">
            {projectInfo.teamName}
            {projectInfo.country ? ` · ${projectInfo.country}` : ''}
          </p>
        )}
      </div>

      {/* Juror scores + advance decision */}
      <div className="flex items-center gap-3 flex-shrink-0">
        {/* Individual juror score pills */}
        {jurorScores && jurorScores.length > 0 ? (
          <div className="flex items-center gap-1" title={jurorScores.map((j) => `${j.jurorName}: ${j.globalScore ?? '—'}/10`).join('\n')}>
            {jurorScores.map((j, i) => (
              <span
                key={i}
                className={cn(
                  'inline-flex items-center justify-center rounded-md px-1.5 py-0.5 text-xs font-medium border',
                  j.globalScore != null && j.globalScore >= 8
                    ? 'bg-emerald-50 text-emerald-700 border-emerald-200'
                    : j.globalScore != null && j.globalScore >= 6
                      ? 'bg-blue-50 text-blue-700 border-blue-200'
                      : j.globalScore != null && j.globalScore >= 4
                        ? 'bg-amber-50 text-amber-700 border-amber-200'
                        : 'bg-red-50 text-red-700 border-red-200',
                )}
                title={`${j.jurorName}: ${j.globalScore ?? '—'}/10`}
              >
                {j.globalScore ?? '—'}
              </span>
            ))}
          </div>
        ) : entry?.avgGlobalScore !== null && entry?.avgGlobalScore !== undefined ? (
          <span className="text-xs text-muted-foreground">
            Avg {entry.avgGlobalScore.toFixed(1)}
          </span>
        ) : null}

        {/* Average score */}
        {entry?.avgGlobalScore !== null && entry?.avgGlobalScore !== undefined && jurorScores && jurorScores.length > 1 && (
          <span className="text-xs font-medium text-muted-foreground" title="Average score">
            = {entry.avgGlobalScore.toFixed(1)}
          </span>
        )}

        {/* Advance decision indicator */}
        <div className={cn(
          'inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium',
          yesCount > 0
            ? 'bg-emerald-100 text-emerald-700'
            : 'bg-gray-100 text-gray-500',
        )}>
          {yesCount > 0 ? (
            <>{yesCount}/{totalJurors} Yes</>
          ) : (
            <>{totalJurors} juror{totalJurors !== 1 ? 's' : ''}</>
          )}
        </div>
      </div>
    </div>
  )
}

// ─── Main component ────────────────────────────────────────────────────────────

export function RankingDashboard({ competitionId: _competitionId, roundId }: RankingDashboardProps) {
  // ─── State ────────────────────────────────────────────────────────────────
  const [selectedProjectId, setSelectedProjectId] = useState<string | null>(null)
  const [localOrder, setLocalOrder] = useState<Record<'STARTUP' | 'BUSINESS_CONCEPT', string[]>>({
    STARTUP: [],
    BUSINESS_CONCEPT: [],
  })
  const initialized = useRef(false)
  const pendingReorderCount = useRef(0)

  // ─── Advance dialog state ─────────────────────────────────────────────────
  const [advanceDialogOpen, setAdvanceDialogOpen] = useState(false)
  const [topNStartup, setTopNStartup] = useState(3)
  const [topNConceptual, setTopNConceptual] = useState(3)
  const [includeReject, setIncludeReject] = useState(false)

  // ─── Expandable review state ──────────────────────────────────────────────
  const [expandedReviews, setExpandedReviews] = useState<Set<string>>(new Set())

  // ─── Sensors ──────────────────────────────────────────────────────────────
  const sensors = useSensors(
    useSensor(PointerSensor),
    useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }),
  )

  // ─── tRPC queries ─────────────────────────────────────────────────────────
  const { data: snapshots, isLoading: snapshotsLoading } = trpc.ranking.listSnapshots.useQuery(
    { roundId },
    { refetchInterval: 30_000 },
  )

  const latestSnapshotId = snapshots?.[0]?.id ?? null
  const latestSnapshot = snapshots?.[0] ?? null

  const { data: snapshot, isLoading: snapshotLoading } = trpc.ranking.getSnapshot.useQuery(
    { snapshotId: latestSnapshotId! },
    { enabled: !!latestSnapshotId },
  )

  const { data: projectStates } = trpc.roundEngine.getProjectStates.useQuery(
    { roundId },
  )

  const { data: projectDetail, isLoading: detailLoading } = trpc.project.getFullDetail.useQuery(
    { id: selectedProjectId! },
    { enabled: !!selectedProjectId },
  )

  const { data: roundData } = trpc.round.getById.useQuery({ id: roundId })

  const { data: evalScores } = trpc.ranking.roundEvaluationScores.useQuery(
    { roundId },
  )

  // ─── tRPC mutations ───────────────────────────────────────────────────────
  const utils = trpc.useUtils()

  const saveReorderMutation = trpc.ranking.saveReorder.useMutation({
    onMutate: () => { pendingReorderCount.current++ },
    onSettled: () => { pendingReorderCount.current-- },
    onError: (err) => toast.error(`Failed to save order: ${err.message}`),
    // Do NOT invalidate getSnapshot — would reset localOrder
  })

  const [rankingInProgress, setRankingInProgress] = useState(false)

  const triggerRankMutation = trpc.ranking.triggerAutoRank.useMutation({
    onMutate: () => setRankingInProgress(true),
    onSuccess: () => {
      toast.success('Ranking complete!')
      initialized.current = false // allow re-init on next snapshot load
      void utils.ranking.listSnapshots.invalidate({ roundId })
      void utils.ranking.getSnapshot.invalidate()
      setRankingInProgress(false)
    },
    onError: (err) => {
      toast.error(err.message)
      setRankingInProgress(false)
    },
  })

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

  const batchRejectMutation = trpc.roundEngine.batchTransition.useMutation({
    onSuccess: (data) => {
      // MEMORY.md: use .length, not direct value comparison
      toast.success(`Rejected ${data.succeeded.length} project(s)`)
      if (data.failed.length > 0) {
        toast.warning(`${data.failed.length} project(s) could not be rejected`)
      }
      void utils.roundEngine.getProjectStates.invalidate({ roundId })
      setAdvanceDialogOpen(false)
    },
    onError: (err) => toast.error(err.message),
  })

  // ─── evalConfig (advancement counts from round config) ────────────────────
  const evalConfig = useMemo(() => {
    if (!roundData?.configJson) return null
    try {
      const config = roundData.configJson as Record<string, unknown>
      const advConfig = config.advancementConfig as Record<string, unknown> | undefined
      return {
        startupAdvanceCount: (advConfig?.startupCount ?? config.startupAdvanceCount ?? 0) as number,
        conceptAdvanceCount: (advConfig?.conceptCount ?? config.conceptAdvanceCount ?? 0) as number,
      }
    } catch { return null }
  }, [roundData])

  // ─── rankingMap (O(1) lookup) ──────────────────────────────────────────────
  const rankingMap = useMemo(() => {
    const map = new Map<string, RankedProjectEntry>()
    if (!snapshot) return map
    const startup = (snapshot.startupRankingJson ?? []) as unknown as RankedProjectEntry[]
    const concept = (snapshot.conceptRankingJson ?? []) as unknown as RankedProjectEntry[]
    ;[...startup, ...concept].forEach((entry) => map.set(entry.projectId, entry))
    return map
  }, [snapshot])

  // ─── projectInfoMap (O(1) lookup by projectId) ────────────────────────────
  const projectInfoMap = useMemo(() => {
    const map = new Map<string, ProjectInfo>()
    if (!projectStates) return map
    for (const ps of projectStates) {
      map.set(ps.project.id, {
        title: ps.project.title,
        teamName: ps.project.teamName,
        country: ps.project.country,
      })
    }
    return map
  }, [projectStates])

  // ─── localOrder init (once, with useRef guard) ────────────────────────────
  useEffect(() => {
    if (!initialized.current && snapshot) {
      const startup = (snapshot.startupRankingJson ?? []) as unknown as RankedProjectEntry[]
      const concept = (snapshot.conceptRankingJson ?? []) as unknown as RankedProjectEntry[]
      setLocalOrder({
        STARTUP: startup.map((r) => r.projectId),
        BUSINESS_CONCEPT: concept.map((r) => r.projectId),
      })
      initialized.current = true
    }
  }, [snapshot])

  // ─── sync advance dialog defaults from config ────────────────────────────
  useEffect(() => {
    if (evalConfig) {
      if (evalConfig.startupAdvanceCount > 0) setTopNStartup(evalConfig.startupAdvanceCount)
      if (evalConfig.conceptAdvanceCount > 0) setTopNConceptual(evalConfig.conceptAdvanceCount)
    }
  }, [evalConfig])

  // ─── handleDragEnd ────────────────────────────────────────────────────────
  function handleDragEnd(category: 'STARTUP' | 'BUSINESS_CONCEPT', event: DragEndEvent) {
    const { active, over } = event
    if (!over || active.id === over.id) return
    setLocalOrder((prev) => {
      const ids = prev[category]
      const newIds = arrayMove(
        ids,
        ids.indexOf(active.id as string),
        ids.indexOf(over.id as string),
      )
      saveReorderMutation.mutate({
        snapshotId: latestSnapshotId!,
        category,
        orderedProjectIds: newIds,
      })
      return { ...prev, [category]: newIds }
    })
  }

  // ─── handleAdvance ────────────────────────────────────────────────────────
  function handleAdvance() {
    const advanceIds = [
      ...localOrder.STARTUP.slice(0, topNStartup),
      ...localOrder.BUSINESS_CONCEPT.slice(0, topNConceptual),
    ]
    const advanceSet = new Set(advanceIds)

    advanceMutation.mutate({ roundId, projectIds: advanceIds })

    if (includeReject) {
      const rejectIds = [...localOrder.STARTUP, ...localOrder.BUSINESS_CONCEPT].filter(
        (id) => !advanceSet.has(id),
      )
      if (rejectIds.length > 0) {
        batchRejectMutation.mutate({ projectIds: rejectIds, roundId, newState: 'REJECTED' })
      }
    }
  }

  // ─── Loading state ────────────────────────────────────────────────────────
  if (snapshotsLoading || snapshotLoading) {
    return (
      <div className="space-y-4">
        <Skeleton className="h-24 w-full rounded-lg" />
        <Skeleton className="h-48 w-full rounded-lg" />
        <Skeleton className="h-48 w-full rounded-lg" />
      </div>
    )
  }

  // ─── Empty state ──────────────────────────────────────────────────────────
  if (!latestSnapshotId) {
    return (
      <div className="space-y-4">
        <Card>
          <CardContent className="flex flex-col items-center justify-center gap-4 py-12 text-center">
            {rankingInProgress ? (
              <>
                <Loader2 className="h-10 w-10 text-blue-500 animate-spin" />
                <div>
                  <p className="font-medium">AI ranking in progress&hellip;</p>
                  <p className="mt-1 text-sm text-muted-foreground">
                    This may take a minute. You can continue working — results will appear automatically.
                  </p>
                </div>
                <div className="h-2 w-48 rounded-full bg-blue-100 dark:bg-blue-900 overflow-hidden">
                  <div className="h-full w-full rounded-full bg-blue-500 animate-pulse" />
                </div>
              </>
            ) : (
              <>
                <BarChart3 className="h-10 w-10 text-muted-foreground" />
                <div>
                  <p className="font-medium">No ranking available yet</p>
                  <p className="mt-1 text-sm text-muted-foreground">
                    Run ranking from the Config tab to generate results, or trigger it now.
                  </p>
                </div>
                <Button
                  onClick={() => triggerRankMutation.mutate({ roundId })}
                  disabled={triggerRankMutation.isPending}
                >
                  <RefreshCw className="mr-2 h-4 w-4" />
                  Run Ranking Now
                </Button>
              </>
            )}
          </CardContent>
        </Card>
      </div>
    )
  }

  // ─── Main content ─────────────────────────────────────────────────────────
  const categoryLabels: Record<'STARTUP' | 'BUSINESS_CONCEPT', string> = {
    STARTUP: 'Startups',
    BUSINESS_CONCEPT: 'Business Concepts',
  }

  return (
    <>
      <div className="space-y-6">
        {/* Header card */}
        <Card>
          <CardHeader className="flex flex-row items-start justify-between gap-4">
            <div className="flex-1 min-w-0">
              <CardTitle className="text-base">Latest Ranking Snapshot</CardTitle>
              {latestSnapshot && (
                <CardDescription className="mt-1 space-y-0.5">
                  <span>
                    Created{' '}
                    {new Date(latestSnapshot.createdAt).toLocaleString(undefined, {
                      dateStyle: 'medium',
                      timeStyle: 'short',
                    })}
                    {latestSnapshot.triggeredBy?.name && ` by ${latestSnapshot.triggeredBy.name}`}
                    {' · '}
                    {latestSnapshot.triggerType}
                  </span>
                  {latestSnapshot.criteriaText && (
                    <span className="block truncate text-xs">
                      Criteria: {latestSnapshot.criteriaText.slice(0, 120)}
                      {latestSnapshot.criteriaText.length > 120 ? '…' : ''}
                    </span>
                  )}
                </CardDescription>
              )}
            </div>
            <div className="flex items-center gap-2 flex-shrink-0">
              <Button
                size="sm"
                variant="outline"
                onClick={() => triggerRankMutation.mutate({ roundId })}
                disabled={rankingInProgress}
              >
                {rankingInProgress ? (
                  <>
                    <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                    Ranking&hellip;
                  </>
                ) : (
                  <>
                    <RefreshCw className="mr-2 h-4 w-4" />
                    Run Ranking
                  </>
                )}
              </Button>
              <Button
                size="sm"
                disabled={saveReorderMutation.isPending || advanceMutation.isPending || !latestSnapshotId}
                onClick={() => setAdvanceDialogOpen(true)}
                className="bg-[#053d57] hover:bg-[#053d57]/90"
              >
                {advanceMutation.isPending ? (
                  <><Loader2 className="h-4 w-4 mr-2 animate-spin" /> Advancing...</>
                ) : (
                  <><Trophy className="h-4 w-4 mr-2" /> Advance Top N</>
                )}
              </Button>
            </div>
          </CardHeader>
        </Card>

        {/* Ranking in-progress banner */}
        {rankingInProgress && (
          <Card className="border-blue-200 bg-blue-50 dark:border-blue-800 dark:bg-blue-950/30">
            <CardContent className="flex items-center gap-3 py-4">
              <Loader2 className="h-5 w-5 animate-spin text-blue-600 dark:text-blue-400 flex-shrink-0" />
              <div className="flex-1 min-w-0">
                <p className="text-sm font-medium text-blue-900 dark:text-blue-200">
                  AI ranking in progress&hellip;
                </p>
                <p className="text-xs text-blue-700 dark:text-blue-400">
                  This may take a minute. You can continue working — results will appear automatically.
                </p>
              </div>
              <div className="h-1.5 w-32 rounded-full bg-blue-200 dark:bg-blue-800 overflow-hidden flex-shrink-0">
                <div className="h-full w-full rounded-full bg-blue-500 animate-pulse" />
              </div>
            </CardContent>
          </Card>
        )}

        {/* Per-category sections */}
        {(['STARTUP', 'BUSINESS_CONCEPT'] as const).map((category) => (
          <Card key={category}>
            <CardHeader>
              <CardTitle className="text-sm font-semibold uppercase tracking-wide text-muted-foreground">
                {categoryLabels[category]}
                {evalConfig && (category === 'STARTUP' ? evalConfig.startupAdvanceCount : evalConfig.conceptAdvanceCount) > 0 && (
                  <span className="ml-2 text-xs font-normal normal-case">
                    (Top {category === 'STARTUP' ? evalConfig.startupAdvanceCount : evalConfig.conceptAdvanceCount} advance)
                  </span>
                )}
              </CardTitle>
            </CardHeader>
            <CardContent>
              {localOrder[category].length === 0 ? (
                <p className="text-sm text-muted-foreground">
                  No {category === 'STARTUP' ? 'startup' : 'business concept'} projects ranked.
                </p>
              ) : (
                <DndContext
                  sensors={sensors}
                  collisionDetection={closestCenter}
                  onDragEnd={(event) => handleDragEnd(category, event)}
                >
                  <SortableContext
                    items={localOrder[category]}
                    strategy={verticalListSortingStrategy}
                  >
                    <AnimatePresence initial={false}>
                      <div className="space-y-2">
                        {localOrder[category].map((projectId, index) => {
                          const advanceCount = category === 'STARTUP'
                            ? (evalConfig?.startupAdvanceCount ?? 0)
                            : (evalConfig?.conceptAdvanceCount ?? 0)
                          const isAdvancing = advanceCount > 0 && index < advanceCount
                          const isCutoffRow = advanceCount > 0 && index === advanceCount - 1

                          return (
                            <React.Fragment key={projectId}>
                              <motion.div
                                layout
                                initial={{ opacity: 0, y: 20 }}
                                animate={{ opacity: 1, y: 0 }}
                                exit={{ opacity: 0, y: -20 }}
                                className={isAdvancing ? 'rounded-lg bg-emerald-50 dark:bg-emerald-950/20' : ''}
                              >
                                <SortableProjectRow
                                  projectId={projectId}
                                  currentRank={index + 1}
                                  entry={rankingMap.get(projectId)}
                                  projectInfo={projectInfoMap.get(projectId)}
                                  jurorScores={evalScores?.[projectId]}
                                  onSelect={() => setSelectedProjectId(projectId)}
                                  isSelected={selectedProjectId === projectId}
                                />
                              </motion.div>
                              {isCutoffRow && (
                                <div className="flex items-center gap-2 py-1">
                                  <div className="flex-1 border-t-2 border-dashed border-emerald-400/60" />
                                  <span className="text-xs font-medium text-emerald-600 dark:text-emerald-400 whitespace-nowrap">
                                    Advancement cutoff — Top {advanceCount}
                                  </span>
                                  <div className="flex-1 border-t-2 border-dashed border-emerald-400/60" />
                                </div>
                              )}
                            </React.Fragment>
                          )
                        })}
                      </div>
                    </AnimatePresence>
                  </SortableContext>
                </DndContext>
              )}
            </CardContent>
          </Card>
        ))}
      </div>

      {/* Advance Top N dialog */}
      <Dialog open={advanceDialogOpen} onOpenChange={setAdvanceDialogOpen}>
        <DialogContent className="sm:max-w-md">
          <DialogHeader>
            <DialogTitle>Advance Top Projects</DialogTitle>
            <DialogDescription>
              Select how many top-ranked projects to advance to the next round per category.
              Projects are advanced in the order shown in the ranking list.
            </DialogDescription>
          </DialogHeader>

          <div className="space-y-4 py-2">
            {/* Top N for STARTUP */}
            {localOrder.STARTUP.length > 0 && (
              <div className="flex items-center gap-3">
                <Label className="w-40 text-sm">Startups to advance</Label>
                <Input
                  type="number"
                  min={0}
                  max={localOrder.STARTUP.length}
                  value={topNStartup}
                  onChange={(e) =>
                    setTopNStartup(
                      Math.max(0, Math.min(localOrder.STARTUP.length, parseInt(e.target.value) || 0)),
                    )
                  }
                  className="w-24"
                />
                <span className="text-xs text-muted-foreground">of {localOrder.STARTUP.length}</span>
              </div>
            )}

            {/* Top N for BUSINESS_CONCEPT */}
            {localOrder.BUSINESS_CONCEPT.length > 0 && (
              <div className="flex items-center gap-3">
                <Label className="w-40 text-sm">Business concepts to advance</Label>
                <Input
                  type="number"
                  min={0}
                  max={localOrder.BUSINESS_CONCEPT.length}
                  value={topNConceptual}
                  onChange={(e) =>
                    setTopNConceptual(
                      Math.max(0, Math.min(localOrder.BUSINESS_CONCEPT.length, parseInt(e.target.value) || 0)),
                    )
                  }
                  className="w-24"
                />
                <span className="text-xs text-muted-foreground">of {localOrder.BUSINESS_CONCEPT.length}</span>
              </div>
            )}

            {/* Optional: also batch-reject non-advanced */}
            <div className="flex items-center gap-2 pt-2 border-t">
              <input
                type="checkbox"
                id="includeReject"
                checked={includeReject}
                onChange={(e) => setIncludeReject(e.target.checked)}
                className="h-4 w-4 accent-[#de0f1e]"
              />
              <Label htmlFor="includeReject" className="text-sm cursor-pointer">
                Also batch-reject non-advanced projects
              </Label>
            </div>

            {/* Preview */}
            <div className="text-xs text-muted-foreground bg-muted/50 rounded-md p-3">
              <p>Advancing: {topNStartup + topNConceptual} projects</p>
              {includeReject && (
                <p>
                  Rejecting:{' '}
                  {localOrder.STARTUP.length - topNStartup + (localOrder.BUSINESS_CONCEPT.length - topNConceptual)}{' '}
                  projects
                </p>
              )}
            </div>
          </div>

          <DialogFooter>
            <Button
              variant="outline"
              onClick={() => setAdvanceDialogOpen(false)}
              disabled={advanceMutation.isPending || batchRejectMutation.isPending}
            >
              Cancel
            </Button>
            <Button
              onClick={handleAdvance}
              disabled={
                advanceMutation.isPending ||
                batchRejectMutation.isPending ||
                topNStartup + topNConceptual === 0
              }
              className="bg-[#053d57] hover:bg-[#053d57]/90"
            >
              {advanceMutation.isPending ? (
                <>
                  <Loader2 className="h-4 w-4 mr-2 animate-spin" /> Advancing...
                </>
              ) : (
                `Advance ${topNStartup + topNConceptual} Project${topNStartup + topNConceptual !== 1 ? 's' : ''}`
              )}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* Side panel Sheet */}
      <Sheet
        open={!!selectedProjectId}
        onOpenChange={(open) => {
          if (!open) setSelectedProjectId(null)
        }}
      >
        <SheetContent className="w-[480px] sm:max-w-[480px] overflow-y-auto">
          <SheetHeader>
            <SheetTitle>{projectDetail?.project.title ?? 'Project Details'}</SheetTitle>
            <SheetDescription>
              {selectedProjectId ? `ID: …${selectedProjectId.slice(-8)}` : ''}
            </SheetDescription>
            {selectedProjectId && (
              <a
                href={`/admin/projects/${selectedProjectId}`}
                target="_blank"
                rel="noopener noreferrer"
                className="inline-flex items-center gap-1.5 text-sm text-primary hover:underline mt-1"
              >
                <ExternalLink className="h-3.5 w-3.5" />
                View Project Page
              </a>
            )}
          </SheetHeader>

          {detailLoading ? (
            <div className="mt-6 space-y-3">
              <Skeleton className="h-16 w-full" />
              <Skeleton className="h-24 w-full" />
              <Skeleton className="h-24 w-full" />
            </div>
          ) : projectDetail ? (
            <div className="mt-6 space-y-6">
              {/* Stats summary */}
              {projectDetail.stats && (
                <div className="grid grid-cols-3 gap-3">
                  <div className="rounded-lg border p-3 text-center">
                    <p className="text-xs text-muted-foreground">Avg Score</p>
                    <p className="mt-1 text-lg font-semibold">
                      {projectDetail.stats.averageGlobalScore?.toFixed(1) ?? '—'}
                    </p>
                  </div>
                  <div className="rounded-lg border p-3 text-center">
                    <p className="text-xs text-muted-foreground">Pass Rate</p>
                    <p className="mt-1 text-lg font-semibold">
                      {projectDetail.stats.totalEvaluations > 0
                        ? `${Math.round((projectDetail.stats.yesVotes / projectDetail.stats.totalEvaluations) * 100)}%`
                        : '—'}
                    </p>
                  </div>
                  <div className="rounded-lg border p-3 text-center">
                    <p className="text-xs text-muted-foreground">Evaluators</p>
                    <p className="mt-1 text-lg font-semibold">
                      {projectDetail.stats.totalEvaluations}
                    </p>
                  </div>
                </div>
              )}

              {/* Per-juror evaluations */}
              <div>
                <h4 className="mb-3 text-sm font-semibold">Juror Evaluations</h4>
                {(() => {
                  const submitted = projectDetail.assignments.filter(
                    (a) => a.evaluation?.status === 'SUBMITTED' && a.round.id === roundId,
                  )
                  if (submitted.length === 0) {
                    return (
                      <p className="text-sm text-muted-foreground">
                        No submitted evaluations for this round.
                      </p>
                    )
                  }
                  return (
                    <div className="space-y-3">
                      {submitted.map((a) => {
                        const isExpanded = expandedReviews.has(a.id)
                        return (
                          <div
                            key={a.id}
                            className="rounded-lg border p-3 cursor-pointer hover:bg-muted/50 transition-colors"
                            onClick={() => setExpandedReviews(prev => {
                              const next = new Set(prev)
                              next.has(a.id) ? next.delete(a.id) : next.add(a.id)
                              return next
                            })}
                          >
                            <div className="flex items-center justify-between">
                              <span className="font-medium text-sm">{a.user?.name ?? a.user?.email ?? 'Unknown'}</span>
                              <div className="flex items-center gap-2">
                                {a.evaluation?.binaryDecision != null && (
                                  <Badge
                                    variant={a.evaluation.binaryDecision ? 'default' : 'destructive'}
                                    className={a.evaluation.binaryDecision ? 'bg-emerald-100 text-emerald-700 hover:bg-emerald-100' : ''}
                                  >
                                    {a.evaluation.binaryDecision ? 'Yes' : 'No'}
                                  </Badge>
                                )}
                                <Badge variant="outline">Score: {a.evaluation?.globalScore?.toFixed(1) ?? '—'}</Badge>
                              </div>
                            </div>
                            {isExpanded && a.evaluation?.feedbackText && (
                              <p className="mt-2 text-sm text-muted-foreground whitespace-pre-wrap border-t pt-2">
                                {a.evaluation.feedbackText}
                              </p>
                            )}
                          </div>
                        )
                      })}
                    </div>
                  )
                })()}
              </div>
            </div>
          ) : null}
        </SheetContent>
      </Sheet>
    </>
  )
}
