'use client'

import { useMemo, useState } from 'react'
import Link from 'next/link'
import { toast } from 'sonner'
import { trpc } from '@/lib/trpc/client'
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from '@/components/ui/table'
import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Skeleton } from '@/components/ui/skeleton'
import { Checkbox } from '@/components/ui/checkbox'
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog'
import {
  Search,
  UserPlus,
  ArrowRight,
  Sparkles,
  Loader2,
  Download,
  X,
  Plus,
} from 'lucide-react'
import { CountryDisplay } from '@/components/shared/country-display'
import { AddProjectDialog } from '@/components/admin/round/project-states-table'

type Filter = 'all' | 'unassigned' | 'assigned' | 'wants_only'

type CompetitionRound = {
  id: string
  name: string
  sortOrder: number
  _count: { projectRoundStates: number }
}

export function MentoringProjectsTable({
  roundId,
  competitionId,
  competitionRounds,
  currentSortOrder,
}: {
  roundId: string
  competitionId: string
  competitionRounds?: CompetitionRound[]
  currentSortOrder?: number
}) {
  const [addProjectOpen, setAddProjectOpen] = useState(false)
  const [search, setSearch] = useState('')
  const [filter, setFilter] = useState<Filter>('all')
  const [selected, setSelected] = useState<Set<string>>(new Set())
  const [bulkOpen, setBulkOpen] = useState(false)
  const [chosenMentorIds, setChosenMentorIds] = useState<Set<string>>(new Set())
  const [mentorSearch, setMentorSearch] = useState('')

  const utils = trpc.useUtils()

  const { data, isLoading } = trpc.round.listMentoringProjects.useQuery(
    { roundId },
    { refetchInterval: 30_000 },
  )

  const { data: importCandidates } =
    trpc.round.getMentoringImportCandidates.useQuery({ roundId })

  const { data: mentorPool } = trpc.mentor.getMentorPool.useQuery(
    {},
    { enabled: bulkOpen },
  )

  const bulkAssignMutation = trpc.mentor.bulkAssign.useMutation({
    onSuccess: (result) => {
      if (result.totalAssigned === 0 && result.totalSkipped > 0) {
        toast.info(
          `No new assignments — every selected mentor is already on every selected project (${result.totalSkipped} pair${result.totalSkipped === 1 ? '' : 's'} skipped).`,
        )
      } else if (result.totalAssigned === 0 && result.ineligibleProjectCount > 0) {
        toast.warning(
          `${result.ineligibleProjectCount} project${result.ineligibleProjectCount === 1 ? '' : 's'} aren't in a mentoring round and were skipped.`,
        )
      } else {
        const mentorCount = result.perMentor.filter((m) => m.assigned > 0).length
        toast.success(
          `Created ${result.totalAssigned} assignment${
            result.totalAssigned === 1 ? '' : 's'
          } across ${result.touchedProjectCount} project${
            result.touchedProjectCount === 1 ? '' : 's'
          }${result.totalSkipped > 0 ? ` (${result.totalSkipped} pair${result.totalSkipped === 1 ? '' : 's'} already existed)` : ''}${
            result.emailsSent > 0
              ? ` · ${result.emailsSent} mentor email${result.emailsSent === 1 ? '' : 's'} sent`
              : ''
          }`,
          {
            description:
              mentorCount > 1
                ? `Each of ${mentorCount} mentors gets a single combined email listing only their new projects.`
                : undefined,
          },
        )
      }
      utils.round.listMentoringProjects.invalidate({ roundId })
      utils.round.getProjectsNeedingMentor.invalidate({ roundId })
      utils.round.getMentoringImportCandidates.invalidate({ roundId })
      utils.mentor.getMentorPool.invalidate()
      utils.mentor.getRoundStats.invalidate({ roundId })
      utils.project.list.invalidate()
      setSelected(new Set())
      setChosenMentorIds(new Set())
      setMentorSearch('')
      setBulkOpen(false)
    },
    onError: (err) => toast.error(err.message),
  })

  const advanceMutation = trpc.round.advanceProjects.useMutation({
    onSuccess: (result) => {
      toast.success(
        `Imported ${result.advancedCount} project${
          result.advancedCount === 1 ? '' : 's'
        } from ${result.targetRoundName ? '' : ''}${
          importCandidates?.priorRound?.name ?? 'the prior round'
        }`,
      )
      utils.round.listMentoringProjects.invalidate({ roundId })
      utils.round.getMentoringImportCandidates.invalidate({ roundId })
      utils.round.getProjectsNeedingMentor.invalidate({ roundId })
    },
    onError: (err) => toast.error(err.message),
  })

  const importBanner = importCandidates?.priorRound &&
    importCandidates.pendingCount > 0 && (
      <div className="flex flex-col gap-2 rounded-md border border-amber-300 bg-amber-50 px-4 py-3 text-sm sm:flex-row sm:items-center sm:justify-between">
        <div className="text-amber-900">
          <span className="font-medium">
            {importCandidates.pendingCount} PASSED project
            {importCandidates.pendingCount === 1 ? '' : 's'}
          </span>{' '}
          from{' '}
          <span className="font-medium">
            {importCandidates.priorRound.name}
          </span>{' '}
          {importCandidates.pendingCount === 1 ? "isn't" : "aren't"} in this
          mentoring round yet.
        </div>
        <Button
          size="sm"
          onClick={() =>
            advanceMutation.mutate({
              roundId: importCandidates.priorRound!.id,
              targetRoundId: roundId,
            })
          }
          disabled={advanceMutation.isPending}
        >
          {advanceMutation.isPending ? (
            <Loader2 className="mr-1.5 h-4 w-4 animate-spin" />
          ) : (
            <Download className="mr-1.5 h-4 w-4" />
          )}
          Import {importCandidates.pendingCount}
        </Button>
      </div>
    )

  const filtered = useMemo(() => {
    if (!data) return []
    const q = search.trim().toLowerCase()
    return data.projects.filter((p) => {
      if (filter === 'unassigned' && p.mentors.length > 0) return false
      if (filter === 'assigned' && p.mentors.length === 0) return false
      if (filter === 'wants_only' && !p.wantsMentorship) return false
      if (!q) return true
      const hay = [
        p.title,
        p.teamName ?? '',
        p.country ?? '',
        ...p.mentors.map((m) => m.name ?? m.email),
      ]
        .join(' ')
        .toLowerCase()
      return hay.includes(q)
    })
  }, [data, search, filter])

  const totals = useMemo(() => {
    if (!data)
      return { total: 0, unassigned: 0, assigned: 0, wants: 0 }
    return {
      total: data.projects.length,
      unassigned: data.projects.filter((p) => p.mentors.length === 0).length,
      assigned: data.projects.filter((p) => p.mentors.length > 0).length,
      wants: data.projects.filter((p) => p.wantsMentorship).length,
    }
  }, [data])

  if (isLoading) {
    return (
      <div className="space-y-2">
        {[1, 2, 3, 4, 5].map((i) => (
          <Skeleton key={i} className="h-14 w-full" />
        ))}
      </div>
    )
  }

  if (!data || data.projects.length === 0) {
    return (
      <div className="space-y-3">
        {importBanner}
        <div className="flex items-center justify-end">
          <Button size="sm" onClick={() => setAddProjectOpen(true)}>
            <Plus className="mr-1.5 h-4 w-4" />
            Add Project to Round
          </Button>
        </div>
        <div className="rounded-md border bg-muted/30 px-4 py-12 text-center text-sm text-muted-foreground">
          No projects in this mentoring round yet. Click{' '}
          <span className="font-medium text-foreground">Add Project to Round</span>{' '}
          above to populate it.
        </div>

        <AddProjectDialog
          open={addProjectOpen}
          onOpenChange={setAddProjectOpen}
          roundId={roundId}
          competitionId={competitionId}
          competitionRounds={competitionRounds}
          currentSortOrder={currentSortOrder}
          onAssigned={() => {
            utils.round.listMentoringProjects.invalidate({ roundId })
            utils.round.getProjectsNeedingMentor.invalidate({ roundId })
            utils.round.getMentoringImportCandidates.invalidate({ roundId })
            utils.mentor.getRoundStats.invalidate({ roundId })
          }}
        />
      </div>
    )
  }

  const Pill = ({
    value,
    label,
    count,
  }: {
    value: Filter
    label: string
    count: number
  }) => (
    <button
      type="button"
      onClick={() => setFilter(value)}
      className={`rounded-md border px-2.5 py-1 text-xs font-medium transition-colors ${
        filter === value
          ? 'border-primary bg-primary text-primary-foreground'
          : 'bg-background hover:bg-muted'
      }`}
    >
      {label}{' '}
      <span className="tabular-nums opacity-80">({count})</span>
    </button>
  )

  return (
    <div className="space-y-3">
      {importBanner}
      <div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
        <div className="flex flex-wrap gap-1.5">
          <Pill value="all" label="All" count={totals.total} />
          <Pill value="unassigned" label="No mentor" count={totals.unassigned} />
          <Pill value="assigned" label="Has mentor" count={totals.assigned} />
          <Pill value="wants_only" label="Wants mentorship" count={totals.wants} />
        </div>
        <div className="flex items-center gap-2">
          <div className="relative w-full sm:w-72">
            <Search className="absolute left-2.5 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-muted-foreground" />
            <Input
              value={search}
              onChange={(e) => setSearch(e.target.value)}
              placeholder="Search projects, teams, or mentors…"
              className="pl-8"
            />
          </div>
          <Button
            size="sm"
            onClick={() => setAddProjectOpen(true)}
            className="shrink-0"
          >
            <Plus className="mr-1 h-4 w-4" />
            Add
          </Button>
        </div>
      </div>

      {selected.size > 0 ? (
        <div className="flex flex-col gap-2 rounded-md border border-primary/30 bg-primary/5 px-4 py-2.5 text-sm sm:flex-row sm:items-center sm:justify-between">
          <div>
            <span className="font-medium">{selected.size}</span>{' '}
            <span className="text-muted-foreground">
              project{selected.size === 1 ? '' : 's'} selected
            </span>
          </div>
          <div className="flex flex-wrap gap-2">
            <Button size="sm" onClick={() => setBulkOpen(true)}>
              <UserPlus className="mr-1.5 h-4 w-4" />
              Assign mentor…
            </Button>
            <Button
              size="sm"
              variant="outline"
              onClick={() => setSelected(new Set())}
            >
              <X className="mr-1 h-4 w-4" />
              Clear
            </Button>
          </div>
        </div>
      ) : (
        <div className="flex items-center justify-between rounded-md border border-dashed bg-muted/20 px-4 py-2 text-xs text-muted-foreground">
          <span>
            Tip: tick checkboxes to bulk-assign one mentor to multiple
            projects in a single click (mentor gets one combined email).
          </span>
          {totals.unassigned > 0 && (
            <button
              type="button"
              className="text-xs font-medium text-foreground hover:underline"
              onClick={() => {
                setFilter('unassigned')
                setSelected(
                  new Set(
                    data.projects
                      .filter((p) => p.mentors.length === 0)
                      .map((p) => p.id),
                  ),
                )
              }}
            >
              Select all {totals.unassigned} without a mentor
            </button>
          )}
        </div>
      )}

      <div className="overflow-hidden rounded-md border">
        <Table>
          <TableHeader>
            <TableRow>
              <TableHead className="w-10">
                <Checkbox
                  checked={
                    filtered.length > 0 &&
                    filtered.every((p) => selected.has(p.id))
                  }
                  onCheckedChange={(checked) => {
                    setSelected((prev) => {
                      const next = new Set(prev)
                      if (checked) {
                        filtered.forEach((p) => next.add(p.id))
                      } else {
                        filtered.forEach((p) => next.delete(p.id))
                      }
                      return next
                    })
                  }}
                  aria-label="Select all visible"
                />
              </TableHead>
              <TableHead>Project</TableHead>
              <TableHead>Wants?</TableHead>
              <TableHead>Mentors</TableHead>
              <TableHead className="w-32 text-right">Action</TableHead>
            </TableRow>
          </TableHeader>
          <TableBody>
            {filtered.length === 0 ? (
              <TableRow>
                <TableCell
                  colSpan={5}
                  className="py-8 text-center text-sm text-muted-foreground"
                >
                  No projects match the current filter.
                </TableCell>
              </TableRow>
            ) : (
              filtered.map((p) => (
                <TableRow
                  key={p.id}
                  data-state={selected.has(p.id) ? 'selected' : undefined}
                >
                  <TableCell>
                    <Checkbox
                      checked={selected.has(p.id)}
                      onCheckedChange={(checked) =>
                        setSelected((prev) => {
                          const next = new Set(prev)
                          if (checked) next.add(p.id)
                          else next.delete(p.id)
                          return next
                        })
                      }
                      aria-label={`Select ${p.title}`}
                    />
                  </TableCell>
                  <TableCell>
                    <div className="font-medium">{p.title}</div>
                    <div className="text-xs text-muted-foreground">
                      {p.teamName ?? '—'}
                      {p.country && (
                        <>
                          {' · '}
                          <CountryDisplay country={p.country} />
                        </>
                      )}
                    </div>
                  </TableCell>
                  <TableCell>
                    <div className="flex flex-col gap-1">
                      {p.wantsMentorship ? (
                        <Badge variant="secondary" className="w-fit text-xs">
                          Requested
                        </Badge>
                      ) : (
                        <span className="text-xs text-muted-foreground">No</span>
                      )}
                      {p.finalistConfirmationStatus !== 'CONFIRMED' && (
                        <span
                          className="text-[10px] uppercase tracking-wide text-amber-700"
                          title="Auto-fill skips projects whose team has not confirmed attendance."
                        >
                          {p.finalistConfirmationStatus
                            ? p.finalistConfirmationStatus.toLowerCase()
                            : 'no confirmation'}
                        </span>
                      )}
                    </div>
                  </TableCell>
                  <TableCell>
                    {p.mentors.length === 0 ? (
                      <span className="text-xs italic text-muted-foreground">
                        Unassigned
                      </span>
                    ) : (
                      <div className="flex flex-wrap gap-1">
                        {p.mentors.map((m) => (
                          <Badge
                            key={m.assignmentId}
                            variant="outline"
                            className="gap-1 text-xs"
                            title={m.email}
                          >
                            {(m.method === 'AI_AUTO' ||
                              m.method === 'AI_SUGGESTED') && (
                              <Sparkles className="h-3 w-3 text-amber-500" />
                            )}
                            {m.name ?? m.email}
                          </Badge>
                        ))}
                      </div>
                    )}
                  </TableCell>
                  <TableCell className="text-right">
                    <Button asChild size="sm" variant="outline">
                      <Link href={`/admin/projects/${p.id}/mentor`}>
                        {p.mentors.length === 0 ? (
                          <>
                            <UserPlus className="mr-1 h-3.5 w-3.5" />
                            Assign
                          </>
                        ) : (
                          <>
                            Open
                            <ArrowRight className="ml-1 h-3.5 w-3.5" />
                          </>
                        )}
                      </Link>
                    </Button>
                  </TableCell>
                </TableRow>
              ))
            )}
          </TableBody>
        </Table>
      </div>

      <Dialog
        open={bulkOpen}
        onOpenChange={(next) => {
          if (!next) {
            setBulkOpen(false)
            setChosenMentorIds(new Set())
            setMentorSearch('')
          }
        }}
      >
        <DialogContent>
          <DialogHeader>
            <DialogTitle>
              Assign mentors to {selected.size} project
              {selected.size === 1 ? '' : 's'}
            </DialogTitle>
            <DialogDescription>
              Tick any number of mentors. Each chosen mentor will be added to
              every selected project they aren&apos;t already on. Each mentor
              receives one combined email; each team receives one intro email
              listing all of their mentors.
            </DialogDescription>
          </DialogHeader>

          <div className="space-y-3">
            {(() => {
              const allMentors = mentorPool?.mentors ?? []
              const chosenMentors = allMentors.filter((m) =>
                chosenMentorIds.has(m.id),
              )
              const upperBound = chosenMentorIds.size * selected.size

              return (
                <>
                  {chosenMentors.length > 0 && (
                    <div className="flex flex-wrap gap-1 rounded-md border bg-muted/30 p-2">
                      {chosenMentors.map((m) => (
                        <Badge
                          key={m.id}
                          variant="secondary"
                          className="gap-1 pl-2 pr-1"
                        >
                          {m.name ?? m.email}
                          <button
                            type="button"
                            aria-label={`Remove ${m.name ?? m.email}`}
                            className="rounded-full p-0.5 hover:bg-foreground/10"
                            onClick={() =>
                              setChosenMentorIds((prev) => {
                                const next = new Set(prev)
                                next.delete(m.id)
                                return next
                              })
                            }
                          >
                            <X className="h-3 w-3" />
                          </button>
                        </Badge>
                      ))}
                    </div>
                  )}

                  <div className="relative">
                    <Search className="absolute left-2.5 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-muted-foreground" />
                    <Input
                      value={mentorSearch}
                      onChange={(e) => setMentorSearch(e.target.value)}
                      placeholder="Search mentor by name, email, country, or expertise…"
                      className="pl-8"
                    />
                  </div>

                  <div className="max-h-72 overflow-y-auto rounded-md border">
                    {(() => {
                      const q = mentorSearch.trim().toLowerCase()
                      const filteredMentors = q
                        ? allMentors.filter((m) =>
                            [
                              m.name ?? '',
                              m.email,
                              m.country ?? '',
                              ...(m.expertiseTags ?? []),
                            ]
                              .join(' ')
                              .toLowerCase()
                              .includes(q),
                          )
                        : allMentors
                      if (allMentors.length === 0) {
                        return (
                          <p className="p-4 text-center text-sm text-muted-foreground">
                            No mentors in the pool yet.{' '}
                            <Link
                              href="/admin/members?tab=mentors"
                              className="underline-offset-2 hover:underline"
                            >
                              Add mentors
                            </Link>
                            .
                          </p>
                        )
                      }
                      if (filteredMentors.length === 0) {
                        return (
                          <p className="p-4 text-center text-sm text-muted-foreground">
                            No mentors match &ldquo;{mentorSearch}&rdquo;.
                          </p>
                        )
                      }
                      return filteredMentors.map((m) => {
                        const isChosen = chosenMentorIds.has(m.id)
                        return (
                          <label
                            key={m.id}
                            className={`flex cursor-pointer items-start gap-3 border-b px-3 py-2 text-sm last:border-b-0 ${
                              isChosen ? 'bg-accent' : 'hover:bg-muted/50'
                            }`}
                          >
                            <Checkbox
                              className="mt-1"
                              checked={isChosen}
                              onCheckedChange={(checked) =>
                                setChosenMentorIds((prev) => {
                                  const next = new Set(prev)
                                  if (checked) next.add(m.id)
                                  else next.delete(m.id)
                                  return next
                                })
                              }
                              aria-label={`Toggle ${m.name ?? m.email}`}
                            />
                            <div className="min-w-0 flex-1">
                              <div className="font-medium">
                                {m.name ?? 'Unnamed'}
                              </div>
                              <div className="truncate text-xs text-muted-foreground">
                                {m.email}
                                {m.country && <> · {m.country}</>}
                              </div>
                              {m.expertiseTags && m.expertiseTags.length > 0 && (
                                <div className="mt-1 flex flex-wrap gap-1">
                                  {m.expertiseTags.slice(0, 4).map((t) => (
                                    <Badge
                                      key={t}
                                      variant="secondary"
                                      className="text-[10px]"
                                    >
                                      {t}
                                    </Badge>
                                  ))}
                                  {m.expertiseTags.length > 4 && (
                                    <Badge
                                      variant="outline"
                                      className="text-[10px]"
                                    >
                                      +{m.expertiseTags.length - 4}
                                    </Badge>
                                  )}
                                </div>
                              )}
                            </div>
                            <div className="shrink-0 text-right text-xs tabular-nums text-muted-foreground">
                              {m.currentAssignments}
                              {m.maxAssignments != null && `/${m.maxAssignments}`}{' '}
                              load
                            </div>
                          </label>
                        )
                      })
                    })()}
                  </div>

                  {chosenMentorIds.size > 0 && (
                    <p className="text-xs text-muted-foreground">
                      Will create up to{' '}
                      <span className="font-medium tabular-nums text-foreground">
                        {upperBound}
                      </span>{' '}
                      assignment{upperBound === 1 ? '' : 's'} (
                      {chosenMentorIds.size} mentor
                      {chosenMentorIds.size === 1 ? '' : 's'} × {selected.size}{' '}
                      project{selected.size === 1 ? '' : 's'}). Pairs that
                      already exist are skipped.
                    </p>
                  )}
                </>
              )
            })()}
          </div>

          <DialogFooter>
            <Button
              variant="outline"
              onClick={() => {
                setBulkOpen(false)
                setChosenMentorIds(new Set())
                setMentorSearch('')
              }}
            >
              Cancel
            </Button>
            <Button
              onClick={() =>
                bulkAssignMutation.mutate({
                  mentorIds: Array.from(chosenMentorIds),
                  projectIds: Array.from(selected),
                })
              }
              disabled={
                chosenMentorIds.size === 0 || bulkAssignMutation.isPending
              }
            >
              {bulkAssignMutation.isPending && (
                <Loader2 className="mr-1.5 h-4 w-4 animate-spin" />
              )}
              Assign {chosenMentorIds.size} mentor
              {chosenMentorIds.size === 1 ? '' : 's'} to {selected.size} project
              {selected.size === 1 ? '' : 's'}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <AddProjectDialog
        open={addProjectOpen}
        onOpenChange={setAddProjectOpen}
        roundId={roundId}
        competitionId={competitionId}
        competitionRounds={competitionRounds}
        currentSortOrder={currentSortOrder}
        onAssigned={() => {
          utils.round.listMentoringProjects.invalidate({ roundId })
          utils.round.getProjectsNeedingMentor.invalidate({ roundId })
          utils.round.getMentoringImportCandidates.invalidate({ roundId })
          utils.mentor.getRoundStats.invalidate({ roundId })
        }}
      />
    </div>
  )
}
