"use client"

// Delte, utelukkende trykkbaserte input-primitiver for hull-for-hull-
// statistikkregistrering (ALDRI dropdowns) -- trukket ut av round-detail.tsx
// sin ScoringWizard (frittstående runder) 2026-08-15 (ADR-071) for gjenbruk
// i org-turneringers nye HoleStatsSheet, som nå har samme statistikkdybde
// (migrasjon 075). Ren UI, ingen datahenting/state utover det som sendes inn.
//
// HoleHistoryPanel (ADR-072) er unntaket -- den HENTER selv (GET .../history),
// siden begge scoringsflytene bruker nøyaktig samme henting/visning og det
// ville vært ren duplisering å bygge den to ganger.

import { useEffect, useState, type ReactNode } from "react"
import { ArrowDown, ArrowLeft, ArrowRight, ArrowUp, ChevronRight, Flag, Minus, Plus, Target } from "lucide-react"
import { cn } from "@/lib/utils"

export function golfTermForScore(n: number, par: number): string | null {
  const diff = n - par
  if (diff <= -3) return "Albatross"
  if (diff === -2) return "Eagle"
  if (diff === -1) return "Birdie"
  if (diff === 0) return "Par"
  if (diff === 1) return "Bogey"
  if (diff === 2) return "Dobbel bogey"
  return null
}

export function NumberPicker({
  label,
  value,
  directValues,
  expandValues,
  expandLabel,
  parValue,
  showGolfTerms,
  maxValue,
  strokesReceived,
  accent,
  onChange,
  readOnly,
}: {
  label: string
  value: number | null
  directValues: number[]
  expandValues: number[]
  expandLabel: string
  // Hullets par -- brukt til golf-term-bildeteksten når showGolfTerms er satt.
  parValue?: number
  // Viser Eagle/Birdie/Par/Bogey/Dobbel bogey under HVERT tall (relativt til
  // parValue), i stedet for kun å merke selve par-knappen -- kun meningsfullt
  // for Slag-velgeren, ikke Putter/Anywayslag.
  showGolfTerms?: boolean
  // Skjuler valg høyere enn dette (f.eks. Putter kan aldri overstige
  // antall slag registrert på hullet) -- ingen vits i å tilby et tall som
  // uansett ville vært selvmotsigende.
  maxValue?: number
  // Spillerens tildelte handicap-slag PÅ DETTE hullet. Når satt (og
  // showGolfTerms er på, dvs. Slag-velgeren), markeres knappen som
  // tilsvarer spillerens PERSONLIGE netto par (rå par + mottatte slag) med
  // en liten, diskret prikk -- tydelig forskjellig fra "valgt"-tilstanden,
  // og de to kan opptre samtidig på samme knapp.
  strokesReceived?: number | null
  // Valgfri egen aksent for seksjonen (brukes til å gi Putter-velgeren en
  // distinkt visuell identitet så den ikke forveksles med Slag-velgeren).
  // Rører IKKE selve tallknappene -- kun tittelrad/ikon.
  accent?: "primary" | "orange"
  onChange: (value: number) => void
  readOnly: boolean
}) {
  const cap = (values: number[]) => (maxValue === undefined ? values : values.filter((n) => n <= maxValue))
  const cappedDirect = cap(directValues)
  const cappedExpand = cap(expandValues)

  const valueInExpand = value !== null && cappedExpand.includes(value)
  const [expanded, setExpanded] = useState(false)
  const showExpanded = expanded || valueInExpand

  const visibleValues = showExpanded ? [...cappedDirect, ...cappedExpand] : cappedDirect

  // Spillerens netto par for hullet = rå par + tildelte slag. Kun beregnet
  // når vi faktisk har begge (Slag-velgeren med kjent strokesReceived).
  const netPar =
    parValue !== undefined && strokesReceived !== null && strokesReceived !== undefined
      ? parValue + strokesReceived
      : null

  // Putter-velgeren får en egen aksent (oransje) og et eget ikon på
  // tittelraden, så den ikke er til å forveksle med Slag-velgeren -- som
  // ellers er nøyaktig samme rutenett. Kun tittelraden/venstre aksentbånd
  // endres; selve tallknappene beholder den etablerte grønne "valgt"-stilen.
  const isOrange = accent === "orange"

  return (
    <div className={cn("flex flex-col gap-2", isOrange && "rounded-2xl border-l-4 border-brand-orange bg-brand-orange/5 py-3 pl-3 pr-1")}>
      <span className="flex items-center gap-2 text-base font-semibold text-foreground">
        {isOrange && (
          <span aria-hidden="true" className="flex size-6 items-center justify-center rounded-lg bg-brand-orange text-brand-orange-foreground">
            <Flag className="size-4" strokeWidth={2.5} />
          </span>
        )}
        {label}
      </span>
      {/* Netto par-forklaring: gjør prikken selvforklarende uten å stole på
          fargesyn alene (tilgjengelighet -- sol/utendørs). Vises kun når det
          faktisk finnes en netto par-markør å forklare. */}
      {netPar !== null && (
        <span className="flex items-center gap-1.5 text-xs font-medium text-muted-foreground">
          <span aria-hidden="true" className="size-2 rounded-full bg-brand-orange ring-2 ring-brand-orange/25" />
          Ditt netto par ({netPar})
        </span>
      )}
      {/* Numpad: tre kolonner, knappene fyller bredden -- store trykkflater
          for bruk utendørs, ofte med sol på skjermen. */}
      <div className="grid max-w-sm grid-cols-3 gap-2.5">
        {visibleValues.map((n) => {
          const selected = value === n
          const isNetPar = netPar !== null && n === netPar
          const term = showGolfTerms && parValue !== undefined ? golfTermForScore(n, parValue) : n === parValue ? "par" : null
          return (
            <button
              key={n}
              type="button"
              disabled={readOnly}
              onClick={() => onChange(n)}
              aria-label={term ? `${label} ${n}, ${term}${isNetPar ? ", ditt netto par" : ""}` : `${label} ${n}${isNetPar ? ", ditt netto par" : ""}`}
              aria-pressed={selected}
              className={cn(
                "relative flex h-16 flex-col items-center justify-center gap-0 rounded-2xl border text-2xl font-extrabold leading-none tabular-nums transition-colors disabled:opacity-100",
                selected
                  ? "border-primary bg-primary text-primary-foreground shadow-sm"
                  : "border-border bg-card text-foreground hover:bg-accent/50",
                // Netto par-knapp som IKKE er valgt: en subtil oransje ring +
                // hint-bakgrunn, tydelig annerledes enn den fylte grønne
                // "valgt"-tilstanden. Prikken øverst til høyre er signalet som
                // holder også når knappen ER valgt (grønn fyll under).
                isNetPar && !selected && "border-brand-orange/60 bg-brand-orange/5",
                readOnly && !selected && "opacity-40",
              )}
            >
              {isNetPar && (
                <span
                  aria-hidden="true"
                  className={cn(
                    "absolute right-1.5 top-1.5 size-2.5 rounded-full bg-brand-orange",
                    // Kontrast-ring så prikken leses uansett om knappen er
                    // grønn (valgt) eller lys (uvalgt).
                    selected ? "ring-2 ring-primary" : "ring-2 ring-card",
                  )}
                />
              )}
              <span>{n}</span>
              {term && (
                <span className={cn("text-[11px] font-bold leading-none", selected ? "text-primary-foreground/80" : "text-muted-foreground")}>
                  {term}
                </span>
              )}
            </button>
          )
        })}
        {!showExpanded && !readOnly && cappedExpand.length > 0 && (
          <button
            type="button"
            onClick={() => setExpanded(true)}
            className="col-span-3 flex h-14 items-center justify-center rounded-2xl border border-dashed border-border bg-card text-lg font-bold text-foreground transition-colors hover:bg-accent/50"
          >
            {expandLabel}
          </button>
        )}
      </div>
    </div>
  )
}

// --- Retningskors (D-pad for Utslag / Innspill) -----------------------------

function DirButton({
  icon: Icon,
  label,
  selected,
  onClick,
  readOnly,
}: {
  icon: typeof ArrowUp
  label: string
  selected: boolean
  onClick: () => void
  readOnly: boolean
}) {
  return (
    <button
      type="button"
      disabled={readOnly}
      onClick={onClick}
      aria-pressed={selected}
      className={cn(
        "flex min-h-16 flex-col items-center justify-center gap-1 rounded-2xl border px-2 py-2 transition-colors disabled:opacity-100",
        selected
          ? "border-primary bg-primary text-primary-foreground shadow-sm"
          : "border-border bg-card text-foreground hover:bg-accent/50",
        readOnly && !selected && "opacity-40",
      )}
    >
      <Icon aria-hidden="true" className="size-6" />
      <span className="text-sm font-bold">{label}</span>
    </button>
  )
}

export function DirectionCross({
  label,
  value,
  onChange,
  readOnly,
  variant,
  centerLabel,
}: {
  label: string
  value: string | null
  onChange: (value: string) => void
  readOnly: boolean
  // "horizontal" = kun venstre/senter/høyre (Utslag); "full" = 5-veis (Innspill)
  variant: "horizontal" | "full"
  centerLabel: string
}) {
  const spacer = <div aria-hidden="true" />
  return (
    <div className="flex flex-col gap-2">
      <span className="text-base font-semibold text-foreground">{label}</span>
      <div className="grid max-w-sm grid-cols-3 gap-2.5">
        {variant === "full" && (
          <>
            {spacer}
            <DirButton icon={ArrowUp} label="Langt" selected={value === "long"} onClick={() => onChange("long")} readOnly={readOnly} />
            {spacer}
          </>
        )}
        <DirButton icon={ArrowLeft} label="Venstre" selected={value === "left"} onClick={() => onChange("left")} readOnly={readOnly} />
        <DirButton
          icon={Target}
          label={centerLabel}
          selected={value === (variant === "full" ? "hit" : "fairway")}
          onClick={() => onChange(variant === "full" ? "hit" : "fairway")}
          readOnly={readOnly}
        />
        <DirButton icon={ArrowRight} label="Høyre" selected={value === "right"} onClick={() => onChange("right")} readOnly={readOnly} />
        {variant === "full" && (
          <>
            {spacer}
            <DirButton icon={ArrowDown} label="Kort" selected={value === "short"} onClick={() => onChange("short")} readOnly={readOnly} />
            {spacer}
          </>
        )}
      </div>
    </div>
  )
}

// --- Choice row (segmented buttons) ----------------------------------------

export function ChoiceRow({
  label,
  options,
  value,
  onChange,
  readOnly,
}: {
  label: string
  options: { value: string; label: string }[]
  value: string | null
  onChange: (value: string) => void
  readOnly: boolean
}) {
  return (
    <div className="flex flex-col gap-2">
      <span className="text-base font-semibold text-foreground">{label}</span>
      <div className="grid grid-cols-3 gap-2">
        {options.map((opt) => {
          const selected = value === opt.value
          return (
            <button
              key={opt.value}
              type="button"
              disabled={readOnly}
              onClick={() => onChange(opt.value)}
              aria-pressed={selected}
              className={cn(
                "flex min-h-12 items-center justify-center rounded-2xl border px-2 text-base font-bold transition-colors disabled:opacity-100",
                selected ? "border-primary bg-primary text-primary-foreground" : "border-border bg-card text-foreground hover:bg-accent/50",
                readOnly && !selected && "opacity-40",
              )}
            >
              {opt.label}
            </button>
          )
        })}
      </div>
    </div>
  )
}

// --- Stepper (+/-) ---------------------------------------------------------

export function Stepper({
  label,
  value,
  onChange,
  readOnly,
  max,
}: {
  label: string
  value: number
  onChange: (value: number) => void
  readOnly: boolean
  // Kan ikke telle høyere enn antall slag registrert på hullet -- f.eks.
  // umulig å ha chippet flere ganger enn totalt antall slag.
  max?: number
}) {
  const atMax = max !== undefined && value >= max
  const atMin = value <= 0
  // Teller-FLIS (ADR-078, 2026-08-16, V0-designet) -- selvstendig kort med
  // etikett + stort tall + -/+ på bunnen, ment for et 2x2-rutenett (se
  // holeDetails-steget i round-detail.tsx/individual-tournament-detail.tsx).
  // Interaksjonskontrakten er uendret: -/tall/+, minus disabled på 0, pluss
  // disabled på max, alle trykkflater >=44px. Kun app-tokens.
  return (
    <div className="flex flex-col items-center gap-3 rounded-2xl border border-border bg-card p-4">
      <span className="text-center text-sm font-bold leading-tight text-foreground">{label}</span>
      {/* Tallet bærer selve informasjonen (aldri farge alene); nullverdi
          dempes kun visuelt via muted-foreground, som fortsatt er AA på
          kort. */}
      <span
        className={cn(
          "text-4xl font-extrabold leading-none tabular-nums",
          atMin ? "text-muted-foreground" : "text-foreground",
        )}
      >
        {value}
      </span>
      <div className="flex w-full items-center gap-2">
        <button
          type="button"
          disabled={readOnly || atMin}
          onClick={() => onChange(Math.max(0, value - 1))}
          aria-label={`Færre ${label}`}
          className="flex h-11 flex-1 items-center justify-center rounded-xl border border-border bg-background text-foreground transition-colors hover:bg-accent/50 disabled:opacity-40"
        >
          <Minus aria-hidden="true" className="size-5" />
        </button>
        <button
          type="button"
          disabled={readOnly || atMax}
          onClick={() => onChange(value + 1)}
          aria-label={`Flere ${label}`}
          className="flex h-11 flex-1 items-center justify-center rounded-xl border border-border bg-background text-foreground transition-colors hover:bg-accent/50 disabled:opacity-40"
        >
          <Plus aria-hidden="true" className="size-5" />
        </button>
      </div>
    </div>
  )
}

export function WizardSection({ title, children }: { title: string; children: ReactNode }) {
  return (
    <section className="flex flex-col gap-4 border-t border-border pt-5 first:border-t-0 first:pt-0">
      <h3 className="text-xs font-bold uppercase tracking-wide text-muted-foreground">{title}</h3>
      {children}
    </section>
  )
}

// --- Spillerens per-hull-historikk (ADR-072) --------------------------------
// "Hvordan spiller jeg egentlig dette hullet?" -- aggregert på tvers av ALLE
// tidligere frittstående runder OG turneringsrunder (custom/håndlagde baner
// og gjestespillere er allerede filtrert bort server-side, se
// app/hole_history.py). Panelet skjuler seg selv (viser ingenting) når
// endepunktet svarer null -- ikke en feil, bare "ingen historikk å vise
// ennå/denne banen støtter det ikke".

type HoleHistoryInstance = {
  source: "personal" | "tournament"
  played_at: string | null
  label: string
  score: number
  par: number
  putts: number | null
  tee_shot_result: string | null
  approach_result: string | null
  chip_count: number | null
  bunker_shot_count: number | null
  penalty_strokes: number | null
  first_putt_distance_bucket: string | null
}

type HoleHistory = {
  times_played: number
  times_personal: number
  times_tournament: number
  average_score: number
  average_score_vs_par: number
  gir_percent: number | null
  fairway_hit_percent: number | null
  average_putts: number | null
  best_score: number
  worst_score: number
  instances: HoleHistoryInstance[]
}

// ADR-079 (2026-08-16): panelet åpner nå den FULLE historikk-skjermen
// (components/hole-history-detail.tsx) ved klikk i stedet for å ekspandere
// en enkel liste inline -- flyttet HIT ut av selve slagvinduet/-arket til
// "skjermen før" (PlayerHoleCards for frittstående runder, "Oversikt"-
// steget for org-turneringer), se round-detail.tsx/individual-tournament-
// detail.tsx for de to bruksstedene.
export function HoleHistoryPanel({ url, onOpenFull }: { url: string; onOpenFull: () => void }) {
  // undefined = laster ennå, null = ingen historikk å vise (custom bane,
  // gjest, eller genuint aldri spilt før).
  const [history, setHistory] = useState<HoleHistory | null | undefined>(undefined)

  useEffect(() => {
    let cancelled = false
    setHistory(undefined)
    fetch(url, { credentials: "include" })
      .then((res) => (res.ok ? res.json() : null))
      .then((data) => {
        if (!cancelled) setHistory(data)
      })
      .catch(() => {
        if (!cancelled) setHistory(null)
      })
    return () => {
      cancelled = true
    }
  }, [url])

  if (!history) return null

  const parSign = history.average_score_vs_par >= 0 ? "+" : ""

  return (
    <button
      type="button"
      onClick={onOpenFull}
      className="flex items-center justify-between gap-3 rounded-2xl border border-border bg-card p-4 text-left transition-colors hover:bg-accent/50"
    >
      <span className="flex flex-col gap-1">
        <span className="text-sm font-bold text-foreground">Din historikk på dette hullet</span>
        <span className="text-xs leading-relaxed text-muted-foreground text-pretty">
          Spilt {history.times_played} {history.times_played === 1 ? "gang" : "ganger"} før
          {" "}({history.times_personal} frittstående, {history.times_tournament} turnering) -- snitt{" "}
          {history.average_score.toFixed(1)} slag ({parSign}
          {history.average_score_vs_par.toFixed(1)} til par)
          {history.gir_percent !== null && `, GIR ${Math.round(history.gir_percent)}%`}
          {history.average_putts !== null && `, ${history.average_putts.toFixed(1)} putter i snitt`}
        </span>
      </span>
      <ChevronRight aria-hidden="true" className="size-4 shrink-0 text-muted-foreground" />
    </button>
  )
}
