"use client"

import { useEffect, useMemo, useRef, useState } from "react"
import { ExternalLink, Loader2, Trash2, TriangleAlert } from "lucide-react"

export type TournamentPlayerRow = {
  participantId: string
  playerId: string
  playerName: string
  handicapSnapshot: number | null
  classId: string | null
  statLevel: "strokes_only" | "strokes_and_putts" | "full"
  status: "active" | "dsq" | "rtd" | "dnf" | "dns"
  gender: "m" | "f" | "x" | null
  birthDate: string | null // ISO "YYYY-MM-DD", null if unknown
}

export type ClassOption = { id: string; name: string }

export type TournamentPlayersRound = {
  id: string
  label: string // e.g. "Runde 1"
  tees: { id: string; name: string }[]
}

export type TournamentPlayersCell = {
  assigned: boolean
  teeId: string | null
  teeName: string | null
}

export type TournamentPlayersTableProps = {
  players: TournamentPlayerRow[]
  classes: ClassOption[]
  rounds: TournamentPlayersRound[]
  // cells[roundId][participantId]
  cells: Record<string, Record<string, TournamentPlayersCell>>
  organizationId: string
  onSetHandicap: (participantId: string, value: number | null) => void
  onSetClass: (participantId: string, classId: string | null) => void
  onSetStatLevel: (participantId: string, statLevel: TournamentPlayerRow["statLevel"]) => void
  onSetStatus: (participantId: string, status: TournamentPlayerRow["status"]) => void
  onRemoveParticipant: (participantId: string) => void
  onChangeGender: (playerId: string, gender: "m" | "f" | "x") => void
  onChangeBirthDate: (playerId: string, birthDate: string) => void
  onToggleRound: (roundId: string, participantId: string, checked: boolean, teeId: string) => void
  onBulkToggleRound: (roundId: string, checked: boolean, teeId: string) => void
  onChangeRoundTee: (roundId: string, participantId: string, teeId: string) => void
  busyRoundIds: string[]
  errors: string[]
}

const STAT_LEVELS: { label: string; value: TournamentPlayerRow["statLevel"] }[] = [
  { label: "Kun slag", value: "strokes_only" },
  { label: "Slag og putt", value: "strokes_and_putts" },
  { label: "Fullt", value: "full" },
]

const STATUSES: { label: string; value: TournamentPlayerRow["status"] }[] = [
  { label: "Aktiv", value: "active" },
  { label: "DSQ", value: "dsq" },
  { label: "RTD", value: "rtd" },
  { label: "DNF", value: "dnf" },
  { label: "DNS", value: "dns" },
]

// Shared control styling so every inline field feels like one family.
const CONTROL =
  "h-9 rounded-lg border border-border bg-background px-2.5 text-sm text-foreground transition-all duration-200 ease-in-out hover:border-primary/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"

function computeAge(birthDate: string): number | null {
  const birth = new Date(birthDate)
  if (Number.isNaN(birth.getTime())) return null
  const now = new Date()
  let age = now.getFullYear() - birth.getFullYear()
  const monthDiff = now.getMonth() - birth.getMonth()
  if (monthDiff < 0 || (monthDiff === 0 && now.getDate() < birth.getDate())) {
    age -= 1
  }
  return age
}

export function TournamentPlayersTable({
  players,
  classes,
  rounds,
  cells,
  organizationId,
  onSetHandicap,
  onSetClass,
  onSetStatLevel,
  onSetStatus,
  onRemoveParticipant,
  onChangeGender,
  onChangeBirthDate,
  onToggleRound,
  onBulkToggleRound,
  onChangeRoundTee,
  busyRoundIds,
  errors,
}: TournamentPlayersTableProps) {
  const showClassColumn = classes.length > 0

  // Local-only: each round's "Standardutslag" (default tee) selection.
  // Resets to each round's first tee whenever the round set changes.
  const [defaultTees, setDefaultTees] = useState<Record<string, string>>({})
  useEffect(() => {
    const next: Record<string, string> = {}
    for (const round of rounds) {
      next[round.id] = round.tees[0]?.id ?? ""
    }
    setDefaultTees(next)
  }, [rounds])

  return (
    <div className="flex flex-col gap-4">
      {errors.length > 0 && (
        <div
          role="alert"
          className="flex flex-col gap-1 rounded-xl border border-destructive/30 bg-destructive/10 p-4 text-destructive"
        >
          <div className="flex items-center gap-2">
            <TriangleAlert aria-hidden="true" className="size-5 shrink-0" />
            <h3 className="text-base font-bold">Noen endringer feilet</h3>
          </div>
          <ul className="pl-7 text-sm leading-relaxed">
            {errors.map((err, i) => (
              <li key={i} className="list-disc">
                {err}
              </li>
            ))}
          </ul>
        </div>
      )}

      <div className="overflow-x-auto rounded-2xl border border-border bg-card shadow-md shadow-black/8">
        <table className="w-full border-collapse text-left">
          <thead>
            <tr className="divide-x divide-border border-b border-border">
              <th
                scope="col"
                className="sticky left-0 z-20 bg-card px-4 py-3 text-xs font-bold uppercase tracking-wide text-muted-foreground"
              >
                Spiller
              </th>
              <th scope="col" className="px-4 py-3 text-xs font-bold uppercase tracking-wide text-muted-foreground">
                Hcp
              </th>
              {showClassColumn && (
                <th scope="col" className="px-4 py-3 text-xs font-bold uppercase tracking-wide text-muted-foreground">
                  Klasse
                </th>
              )}
              <th scope="col" className="px-4 py-3 text-xs font-bold uppercase tracking-wide text-muted-foreground">
                Statistikknivå
              </th>
              <th scope="col" className="px-4 py-3 text-xs font-bold uppercase tracking-wide text-muted-foreground">
                Status
              </th>
              <th scope="col" className="px-4 py-3 text-xs font-bold uppercase tracking-wide text-muted-foreground">
                Kjønn
              </th>
              <th scope="col" className="px-4 py-3 text-xs font-bold uppercase tracking-wide text-muted-foreground">
                Alder
              </th>
              {rounds.map((round) => {
                const busy = busyRoundIds.includes(round.id)
                const assignedCount = players.filter(
                  (p) => cells[round.id]?.[p.participantId]?.assigned,
                ).length
                const allAssigned = players.length > 0 && assignedCount === players.length
                const someAssigned = assignedCount > 0 && assignedCount < players.length
                return (
                  <th
                    key={round.id}
                    scope="col"
                    className="min-w-52 px-4 py-3 align-top text-xs font-bold uppercase tracking-wide text-muted-foreground"
                  >
                    <div className="flex flex-col gap-2">
                      <div className="flex items-center gap-2">
                        <span>{round.label}</span>
                        {busy && (
                          <span className="flex items-center gap-1 normal-case text-primary">
                            <Loader2 aria-hidden="true" className="size-3.5 animate-spin" />
                            <span className="text-[11px] font-semibold">Oppdaterer</span>
                          </span>
                        )}
                      </div>
                      <label className="flex flex-col gap-1 normal-case">
                        <span className="text-[11px] font-semibold text-muted-foreground">Standardutslag</span>
                        <select
                          aria-label={`Standardutslag for ${round.label}`}
                          className={CONTROL}
                          value={defaultTees[round.id] ?? ""}
                          disabled={busy}
                          onChange={(e) =>
                            setDefaultTees((prev) => ({ ...prev, [round.id]: e.target.value }))
                          }
                        >
                          {round.tees.map((tee) => (
                            <option key={tee.id} value={tee.id}>
                              {tee.name}
                            </option>
                          ))}
                        </select>
                      </label>
                      <BulkCheckbox
                        checked={allAssigned}
                        indeterminate={someAssigned}
                        disabled={busy || players.length === 0}
                        label="Velg alle"
                        onChange={(next) =>
                          onBulkToggleRound(round.id, next, defaultTees[round.id] ?? round.tees[0]?.id ?? "")
                        }
                      />
                    </div>
                  </th>
                )
              })}
              <th scope="col" className="px-4 py-3 text-xs font-bold uppercase tracking-wide text-muted-foreground">
                Spillerpool
              </th>
              <th scope="col" className="px-4 py-3 text-right text-xs font-bold uppercase tracking-wide text-muted-foreground">
                Fjern
              </th>
            </tr>
          </thead>
          <tbody className="divide-y divide-border">
            {players.map((player) => (
              <PlayerRow
                key={player.participantId}
                player={player}
                classes={classes}
                showClassColumn={showClassColumn}
                rounds={rounds}
                cells={cells}
                organizationId={organizationId}
                defaultTees={defaultTees}
                busyRoundIds={busyRoundIds}
                onSetHandicap={onSetHandicap}
                onSetClass={onSetClass}
                onSetStatLevel={onSetStatLevel}
                onSetStatus={onSetStatus}
                onRemoveParticipant={onRemoveParticipant}
                onChangeGender={onChangeGender}
                onChangeBirthDate={onChangeBirthDate}
                onToggleRound={onToggleRound}
                onChangeRoundTee={onChangeRoundTee}
              />
            ))}
          </tbody>
        </table>
      </div>
    </div>
  )
}

function BulkCheckbox({
  checked,
  indeterminate,
  disabled,
  label,
  onChange,
}: {
  checked: boolean
  indeterminate: boolean
  disabled: boolean
  label: string
  onChange: (next: boolean) => void
}) {
  const ref = useRef<HTMLInputElement>(null)
  useEffect(() => {
    if (ref.current) ref.current.indeterminate = indeterminate && !checked
  }, [indeterminate, checked])
  return (
    <label className="flex items-center gap-2 normal-case">
      <input
        ref={ref}
        type="checkbox"
        checked={checked}
        disabled={disabled}
        onChange={(e) => onChange(e.target.checked)}
        className="size-5 rounded border-border text-primary transition-all duration-200 ease-in-out focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
      />
      <span className="text-[11px] font-semibold text-muted-foreground">{label}</span>
    </label>
  )
}

function PlayerRow({
  player,
  classes,
  showClassColumn,
  rounds,
  cells,
  organizationId,
  defaultTees,
  busyRoundIds,
  onSetHandicap,
  onSetClass,
  onSetStatLevel,
  onSetStatus,
  onRemoveParticipant,
  onChangeGender,
  onChangeBirthDate,
  onToggleRound,
  onChangeRoundTee,
}: {
  player: TournamentPlayerRow
  classes: ClassOption[]
  showClassColumn: boolean
  rounds: TournamentPlayersRound[]
  cells: Record<string, Record<string, TournamentPlayersCell>>
  organizationId: string
  defaultTees: Record<string, string>
  busyRoundIds: string[]
  onSetHandicap: (participantId: string, value: number | null) => void
  onSetClass: (participantId: string, classId: string | null) => void
  onSetStatLevel: (participantId: string, statLevel: TournamentPlayerRow["statLevel"]) => void
  onSetStatus: (participantId: string, status: TournamentPlayerRow["status"]) => void
  onRemoveParticipant: (participantId: string) => void
  onChangeGender: (playerId: string, gender: "m" | "f" | "x") => void
  onChangeBirthDate: (playerId: string, birthDate: string) => void
  onToggleRound: (roundId: string, participantId: string, checked: boolean, teeId: string) => void
  onChangeRoundTee: (roundId: string, participantId: string, teeId: string) => void
}) {
  // Handicap is a local draft committed on blur, not per-keystroke.
  const [hcpDraft, setHcpDraft] = useState(
    player.handicapSnapshot === null ? "" : String(player.handicapSnapshot),
  )
  useEffect(() => {
    setHcpDraft(player.handicapSnapshot === null ? "" : String(player.handicapSnapshot))
  }, [player.handicapSnapshot])

  const age = player.birthDate ? computeAge(player.birthDate) : null
  const statusAbnormal = player.status !== "active"

  function commitHcp() {
    const trimmed = hcpDraft.trim()
    if (trimmed === "") {
      onSetHandicap(player.participantId, null)
      return
    }
    const num = Number(trimmed)
    if (Number.isNaN(num)) {
      // Revert bad input back to the last known good value.
      setHcpDraft(player.handicapSnapshot === null ? "" : String(player.handicapSnapshot))
      return
    }
    const clamped = Math.min(54, Math.max(-10, num))
    onSetHandicap(player.participantId, clamped)
  }

  return (
    <tr className="divide-x divide-border transition-colors duration-200 ease-in-out hover:bg-accent/40">
      <th
        scope="row"
        className="sticky left-0 z-10 bg-card px-4 py-3 text-left align-middle text-sm font-bold text-foreground"
      >
        {player.playerName}
      </th>

      <td className="px-4 py-3 align-middle">
        <input
          type="number"
          inputMode="decimal"
          step={0.1}
          min={-10}
          max={54}
          aria-label={`Handicap for ${player.playerName}`}
          value={hcpDraft}
          onChange={(e) => setHcpDraft(e.target.value)}
          onBlur={commitHcp}
          className={`${CONTROL} w-20 text-right tabular-nums`}
        />
      </td>

      {showClassColumn && (
        <td className="px-4 py-3 align-middle">
          <select
            aria-label={`Klasse for ${player.playerName}`}
            className={`${CONTROL} w-40`}
            value={player.classId ?? ""}
            onChange={(e) => onSetClass(player.participantId, e.target.value === "" ? null : e.target.value)}
          >
            <option value="">Ingen klasse</option>
            {classes.map((c) => (
              <option key={c.id} value={c.id}>
                {c.name}
              </option>
            ))}
          </select>
        </td>
      )}

      <td className="px-4 py-3 align-middle">
        <select
          aria-label={`Statistikknivå for ${player.playerName}`}
          className={`${CONTROL} w-36`}
          value={player.statLevel}
          onChange={(e) => onSetStatLevel(player.participantId, e.target.value as TournamentPlayerRow["statLevel"])}
        >
          {STAT_LEVELS.map((s) => (
            <option key={s.value} value={s.value}>
              {s.label}
            </option>
          ))}
        </select>
      </td>

      <td className="px-4 py-3 align-middle">
        <select
          aria-label={`Status for ${player.playerName}`}
          className={`${CONTROL} w-28 ${
            statusAbnormal ? "border-destructive/40 bg-destructive/10 text-destructive" : ""
          }`}
          value={player.status}
          onChange={(e) => onSetStatus(player.participantId, e.target.value as TournamentPlayerRow["status"])}
        >
          {STATUSES.map((s) => (
            <option key={s.value} value={s.value}>
              {s.label}
            </option>
          ))}
        </select>
      </td>

      <td className="px-4 py-3 align-middle">
        <select
          aria-label={`Kjønn for ${player.playerName}`}
          className={`${CONTROL} w-28`}
          value={player.gender ?? ""}
          onChange={(e) => onChangeGender(player.playerId, e.target.value as "m" | "f" | "x")}
        >
          <option value="" disabled>
            Ikke satt
          </option>
          <option value="m">Mann</option>
          <option value="f">Kvinne</option>
          <option value="x">Annet</option>
        </select>
      </td>

      <td className="px-4 py-3 align-middle">
        <div className="flex items-center gap-2">
          <input
            type="date"
            aria-label={`Fødselsdato for ${player.playerName}`}
            className={`${CONTROL} w-40`}
            value={player.birthDate ?? ""}
            onChange={(e) => onChangeBirthDate(player.playerId, e.target.value)}
          />
          <span className="min-w-12 text-xs font-semibold tabular-nums text-muted-foreground">
            {age !== null ? `${age} år` : "Ukjent"}
          </span>
        </div>
      </td>

      {rounds.map((round) => {
        const cell = cells[round.id]?.[player.participantId]
        const assigned = cell?.assigned ?? false
        const busy = busyRoundIds.includes(round.id)
        return (
          <td key={round.id} className="px-4 py-3 align-middle">
            <div className="flex items-center gap-2">
              <label className="flex items-center gap-2">
                <input
                  type="checkbox"
                  checked={assigned}
                  disabled={busy}
                  aria-label={`${player.playerName} spiller ${round.label}`}
                  onChange={(e) => {
                    const checked = e.target.checked
                    const teeId = checked
                      ? defaultTees[round.id] ?? round.tees[0]?.id ?? ""
                      : cell?.teeId ?? round.tees[0]?.id ?? ""
                    onToggleRound(round.id, player.participantId, checked, teeId)
                  }}
                  className="size-5 rounded border-border text-primary transition-all duration-200 ease-in-out focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
                />
                <span className="text-xs font-semibold text-muted-foreground">
                  {assigned ? "Spiller" : "Ikke satt"}
                </span>
              </label>
              {assigned && (
                <select
                  aria-label={`Utslag for ${player.playerName} i ${round.label}`}
                  className={`${CONTROL} w-28`}
                  value={cell?.teeId ?? ""}
                  disabled={busy}
                  onChange={(e) => onChangeRoundTee(round.id, player.participantId, e.target.value)}
                >
                  {round.tees.map((tee) => (
                    <option key={tee.id} value={tee.id}>
                      {tee.name}
                    </option>
                  ))}
                </select>
              )}
            </div>
          </td>
        )
      })}

      <td className="px-4 py-3 align-middle">
        <a
          href={`/organizations/${organizationId}/players?highlight=${player.playerId}`}
          className="inline-flex items-center gap-1.5 text-xs font-semibold text-muted-foreground underline-offset-2 transition-colors duration-200 ease-in-out hover:text-foreground hover:underline"
        >
          <ExternalLink aria-hidden="true" className="size-3.5" />
          Rediger i spillerpoolen
        </a>
      </td>

      <td className="px-4 py-3 text-right align-middle">
        <button
          type="button"
          aria-label={`Fjern ${player.playerName}`}
          onClick={() => onRemoveParticipant(player.participantId)}
          className="inline-flex size-9 items-center justify-center rounded-lg text-muted-foreground transition-all duration-200 ease-in-out hover:bg-destructive/10 hover:text-destructive focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring active:scale-95"
        >
          <Trash2 aria-hidden="true" className="size-4" />
        </button>
      </td>
    </tr>
  )
}
