"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" },
]

// Spreadsheet cell control: flat, fills the whole cell, no border of its own.
// The grid lines define the structure; controls only light up on hover/focus.
const CELL =
  "h-full w-full border-0 bg-transparent px-2 py-1.5 text-[13px] leading-tight text-foreground outline-none transition-colors hover:bg-accent/40 focus-visible:bg-background focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"

// Compact header control (round default-tee select).
const HEAD_CELL =
  "h-7 w-full rounded-md border border-border bg-background px-1.5 text-xs font-medium text-foreground outline-none transition-colors hover:border-primary/40 focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"

// Shared cell frame: thin grid lines, zero padding (the control supplies it).
const TD = "border-b border-r border-border p-0 align-middle"
const TH =
  "border-b border-r border-border bg-muted px-2 py-2 text-left text-[11px] font-bold uppercase tracking-wide text-muted-foreground"

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-xl border border-border bg-card shadow-sm shadow-black/5">
        {/* Fluid layout: the table fills the available width instead of leaving
            dead space and pushing round columns off-screen. */}
        <table className="w-full border-collapse text-left [&_td]:last:border-r-0 [&_th]:last:border-r-0">
          <colgroup>
            <col className="w-[13rem]" />
            <col className="w-[5.5rem]" />
            {showClassColumn && <col className="w-[9rem]" />}
            <col className="w-[9rem]" />
            <col className="w-[7rem]" />
            <col className="w-[7rem]" />
            <col className="w-[10rem]" />
            {rounds.map((r) => (
              <col key={r.id} />
            ))}
            <col className="w-[5.5rem]" />
          </colgroup>
          <thead>
            <tr>
              <th
                scope="col"
                className={`${TH} sticky left-0 top-0 z-30`}
              >
                Spiller
              </th>
              <th scope="col" className={`${TH} sticky top-0 z-20 text-right`}>
                Hcp
              </th>
              {showClassColumn && (
                <th scope="col" className={`${TH} sticky top-0 z-20`}>
                  Klasse
                </th>
              )}
              <th scope="col" className={`${TH} sticky top-0 z-20`}>
                Statistikknivå
              </th>
              <th scope="col" className={`${TH} sticky top-0 z-20`}>
                Status
              </th>
              <th scope="col" className={`${TH} sticky top-0 z-20`}>
                Kjønn
              </th>
              <th scope="col" className={`${TH} sticky top-0 z-20`}>
                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={`${TH} sticky top-0 z-20 min-w-[9.5rem] align-top`}
                  >
                    <div className="flex flex-col gap-1.5">
                      <div className="flex items-center justify-between 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-[10px] font-semibold">Oppdaterer</span>
                          </span>
                        )}
                      </div>
                      <select
                        aria-label={`Standardutslag for ${round.label}`}
                        className={HEAD_CELL}
                        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>
                      <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={`${TH} sticky top-0 z-20 text-center`}>
                <span className="sr-only">Handlinger</span>
                <span aria-hidden="true">···</span>
              </th>
            </tr>
          </thead>
          <tbody>
            {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-1.5 normal-case">
      <input
        ref={ref}
        type="checkbox"
        checked={checked}
        disabled={disabled}
        onChange={(e) => onChange(e.target.checked)}
        className="size-4 rounded border-border text-primary outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
      />
      <span className="text-[10px] 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
    }
    // Komma-desimal (norsk skrivemåte, "12,4") skal fungere likt som punktum
    // -- 2026-08-19, bruker: "jeg vil at det skal være irrelevant".
    const num = Number(trimmed.replace(",", "."))
    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="group h-9">
      <th
        scope="row"
        className={`${TD} sticky left-0 z-10 bg-card px-2 py-1.5 text-left text-[13px] font-semibold text-foreground group-hover:bg-accent/30`}
      >
        {player.playerName}
      </th>

      <td className={TD}>
        <input
          // type="text" (ikke "number") -- native number-inputs blokkerer
          // komma-tegnet i de fleste nettlesere FØR det når JS i det hele
          // tatt, uansett hva onBlur-parsingen gjør. inputMode="decimal"
          // beholdes for riktig mobiltastatur. 2026-08-19.
          inputMode="decimal"
          aria-label={`Handicap for ${player.playerName}`}
          value={hcpDraft}
          onChange={(e) => setHcpDraft(e.target.value)}
          onBlur={commitHcp}
          className={`${CELL} text-right tabular-nums`}
        />
      </td>

      {showClassColumn && (
        <td className={TD}>
          <select
            aria-label={`Klasse for ${player.playerName}`}
            className={CELL}
            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={TD}>
        <select
          aria-label={`Statistikknivå for ${player.playerName}`}
          className={CELL}
          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={TD}>
        <select
          aria-label={`Status for ${player.playerName}`}
          className={`${CELL} ${statusAbnormal ? "bg-destructive/10 font-semibold text-destructive hover:bg-destructive/15" : ""}`}
          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={TD}>
        <select
          aria-label={`Kjønn for ${player.playerName}`}
          className={CELL}
          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={TD}>
        <div className="flex items-center">
          <input
            type="date"
            aria-label={`Fødselsdato for ${player.playerName}`}
            className={`${CELL} min-w-0`}
            value={player.birthDate ?? ""}
            onChange={(e) => onChangeBirthDate(player.playerId, e.target.value)}
          />
          <span className="shrink-0 whitespace-nowrap px-1.5 text-[11px] 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={TD}>
            <div className="flex items-center gap-1.5 px-2">
              <input
                type="checkbox"
                checked={assigned}
                disabled={busy}
                aria-label={`${player.playerName} spiller ${round.label}`}
                title={assigned ? "Spiller runden" : "Spiller ikke runden"}
                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-4 shrink-0 rounded border-border text-primary outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
              />
              {assigned ? (
                <select
                  aria-label={`Utslag for ${player.playerName} i ${round.label}`}
                  className="h-7 min-w-0 flex-1 rounded-md border border-border bg-background px-1.5 text-xs text-foreground outline-none transition-colors hover:border-primary/40 focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
                  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>
              ) : (
                <span aria-hidden="true" className="flex-1 text-xs text-muted-foreground/60">
                  —
                </span>
              )}
            </div>
          </td>
        )
      })}

      <td className={TD}>
        <div className="flex items-center justify-center gap-0.5 px-1">
          <a
            href={`/organizations/${organizationId}/players?highlight=${player.playerId}`}
            aria-label={`Rediger ${player.playerName} i spillerpoolen`}
            title="Rediger i spillerpoolen"
            className="inline-flex size-7 items-center justify-center rounded-md text-muted-foreground outline-none transition-colors hover:bg-accent/60 hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring"
          >
            <ExternalLink aria-hidden="true" className="size-4" />
          </a>
          <button
            type="button"
            aria-label={`Fjern ${player.playerName}`}
            title="Fjern spiller"
            onClick={() => onRemoveParticipant(player.participantId)}
            className="inline-flex size-7 items-center justify-center rounded-md text-muted-foreground outline-none transition-colors hover:bg-destructive/10 hover:text-destructive focus-visible:ring-2 focus-visible:ring-ring active:scale-95"
          >
            <Trash2 aria-hidden="true" className="size-4" />
          </button>
        </div>
      </td>
    </tr>
  )
}
