'use client'

import { 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,
} from 'lucide-react'
import type { RankedProjectEntry } from '@/server/services/ai-ranking'

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

type RankingDashboardProps = {
  competitionId: string
  roundId: string
}

type SortableProjectRowProps = {
  projectId: string
  currentRank: number
  entry: RankedProjectEntry | undefined
  onSelect: () => void
  isSelected: boolean
}

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

function SortableProjectRow({
  projectId,
  currentRank,
  entry,
  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

  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 identifier */}
      <div className="flex-1 min-w-0">
        <p className="text-sm font-medium truncate">
          Project …{projectId.slice(-6)}
        </p>
      </div>

      {/* Stats */}
      {entry && (
        <div className="flex items-center gap-4 flex-shrink-0 text-xs text-muted-foreground">
          <span title="Composite score">
            <BarChart3 className="inline h-3 w-3 mr-0.5" />
            {Math.round(entry.compositeScore * 100)}%
          </span>
          {entry.avgGlobalScore !== null && (
            <span title="Average global score">
              Avg {entry.avgGlobalScore.toFixed(1)}
            </span>
          )}
          <span title="Pass rate">
            Pass {Math.round(entry.passRate * 100)}%
          </span>
          <span title="Evaluator count">
            {entry.evaluatorCount} juror{entry.evaluatorCount !== 1 ? 's' : ''}
          </span>
        </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)

  // ─── 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: projectDetail, isLoading: detailLoading } = trpc.project.getFullDetail.useQuery(
    { id: selectedProjectId! },
    { enabled: !!selectedProjectId },
  )

  // ─── 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 triggerRankMutation = trpc.ranking.triggerAutoRank.useMutation({
    onSuccess: () => {
      toast.success('Ranking complete. Reload to see results.')
      initialized.current = false // allow re-init on next snapshot load
      void utils.ranking.listSnapshots.invalidate({ roundId })
    },
    onError: (err) => toast.error(err.message),
  })

  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),
  })

  // ─── 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])

  // ─── 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])

  // ─── 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 (
      <Card>
        <CardContent className="flex flex-col items-center justify-center gap-4 py-12 text-center">
          <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}
          >
            {triggerRankMutation.isPending ? (
              <Loader2 className="mr-2 h-4 w-4 animate-spin" />
            ) : (
              <RefreshCw className="mr-2 h-4 w-4" />
            )}
            Run Ranking Now
          </Button>
        </CardContent>
      </Card>
    )
  }

  // ─── 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={triggerRankMutation.isPending}
              >
                {triggerRankMutation.isPending ? (
                  <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                ) : (
                  <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>

        {/* 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]}
              </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) => (
                          <motion.div
                            key={projectId}
                            layout
                            initial={{ opacity: 0 }}
                            animate={{ opacity: 1 }}
                            exit={{ opacity: 0 }}
                            transition={{ duration: 0.15 }}
                          >
                            <SortableProjectRow
                              projectId={projectId}
                              currentRank={index + 1}
                              entry={rankingMap.get(projectId)}
                              onSelect={() => setSelectedProjectId(projectId)}
                              isSelected={selectedProjectId === projectId}
                            />
                          </motion.div>
                        ))}
                      </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>
          </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) => (
                        <div key={a.id} className="rounded-lg border p-3 space-y-2">
                          <div className="flex items-center justify-between gap-2">
                            <p className="text-sm font-medium truncate">{a.user.name ?? a.user.email}</p>
                            <div className="flex items-center gap-2 flex-shrink-0">
                              {a.evaluation?.globalScore !== null && a.evaluation?.globalScore !== undefined && (
                                <Badge variant="outline" className="text-xs">
                                  Score: {a.evaluation.globalScore.toFixed(1)}
                                </Badge>
                              )}
                              {a.evaluation?.binaryDecision !== null && a.evaluation?.binaryDecision !== undefined && (
                                <Badge
                                  className={cn(
                                    'text-xs',
                                    a.evaluation.binaryDecision
                                      ? 'bg-green-100 text-green-700 hover:bg-green-100'
                                      : 'bg-red-100 text-red-700 hover:bg-red-100',
                                  )}
                                >
                                  {a.evaluation.binaryDecision ? 'Yes' : 'No'}
                                </Badge>
                              )}
                            </div>
                          </div>
                          {a.evaluation?.feedbackText && (
                            <p className="text-xs text-muted-foreground leading-relaxed">
                              {a.evaluation.feedbackText}
                            </p>
                          )}
                        </div>
                      ))}
                    </div>
                  )
                })()}
              </div>
            </div>
          ) : null}
        </SheetContent>
      </Sheet>
    </>
  )
}
