"use client"

import { apiGenderOf, lookupKnownGuest, searchAccounts } from "@/lib/ny-runde/api"
import type { Account, Course, Gender, KnownGuest, Player, StatLevel } from "@/lib/ny-runde/types"
import { cn } from "@/lib/utils"
import { ChevronDown, Search, Sparkles, UserPlus, X } from "lucide-react"
import { useEffect, useMemo, useRef, useState } from "react"
import { Avatar, Field, NativeSelect, Pill, TextInput, ToggleButton, useDebouncedValue } from "./primitives"
import type { Tee } from "@/lib/ny-runde/types"
import { useWizard } from "./wizard-context"

const GENDERS: { value: Gender; label: string }[] = [
  { value: "mann", label: "Mann" },
  { value: "kvinne", label: "Kvinne" },
  { value: "annet", label: "Annet" },
]

const STAT: { value: StatLevel; label: string }[] = [
  { value: "score", label: "Kun slag" },
  { value: "score_putts", label: "Slag + putter" },
  { value: "full", label: "Alt" },
]

let keyCounter = 0
function nextKey() {
  keyCounter += 1
  return `p-${Date.now()}-${keyCounter}`
}

function teeName(course: Course | undefined, teeId?: string) {
  if (!course || !teeId) return "Ikke valgt"
  return course.tees.find((t) => t.id === teeId)?.name ?? "Ikke valgt"
}

function compatibleTees(course: Course | undefined, gender?: Gender) {
  if (!course) return []
  if (!gender) return course.tees // ukjent kjønn (nylig lenket konto): vis alle
  const g = apiGenderOf(gender)
  if (g === "x") return course.tees
  return course.tees.filter((t) => t.genders.includes(g))
}

export function Step3Players() {
  const { state, patch } = useWizard()
  const [adding, setAdding] = useState(false)

  function updatePlayer(key: string, p: Partial<Player>) {
    patch({ players: state.players.map((pl) => (pl.key === key ? { ...pl, ...p } : pl)) })
  }
  function removePlayer(key: string) {
    patch({ players: state.players.filter((pl) => pl.key !== key) })
  }
  function addPlayer(p: Player) {
    patch({ players: [...state.players, p] })
    setAdding(false)
  }

  return (
    <div className="flex flex-col gap-4">
      <div>
        <h2 className="text-lg font-semibold tracking-tight text-[var(--nr-ink)]">Spillere</h2>
        <p className="text-sm text-[var(--nr-muted)]">
          {state.players.length} {state.players.length === 1 ? "spiller" : "spillere"} i runden.
        </p>
      </div>

      <ul className="flex flex-col gap-2">
        {state.players.map((player) => (
          <li key={player.key}>
            <PlayerCard
              player={player}
              course={state.course}
              onChange={(p) => updatePlayer(player.key, p)}
              onRemove={() => removePlayer(player.key)}
            />
          </li>
        ))}
      </ul>

      {adding ? (
        <AddPlayerPanel
          course={state.course}
          // Standard for EN ANNEN spiller enn den som fører score er "Kun
          // slag", uansett hva scorefører selv har valgt for seg selv
          // (2026-08-20 brukerfunn -- speilet tidligere feilaktig
          // state.statLevel, som normalt er scoreførerens EGET, ofte
          // høyere nivå). Organisatoren kan fortsatt sette et høyere nivå
          // manuelt per medspiller.
          defaultStat="score"
          existing={state.players}
          onCancel={() => setAdding(false)}
          onAdd={addPlayer}
        />
      ) : (
        <button
          type="button"
          onClick={() => setAdding(true)}
          className="inline-flex min-h-11 items-center justify-center gap-2 rounded-xl border border-dashed border-[var(--nr-border-strong)] bg-[var(--nr-surface)] px-4 text-sm font-medium text-[var(--nr-accent)] transition-colors hover:bg-[var(--nr-surface-2)] focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-[var(--nr-accent-ring)]/40"
        >
          <UserPlus className="h-4 w-4" aria-hidden="true" />
          Medspiller
        </button>
      )}
    </div>
  )
}

/* ------------------------------------------------------------------ */
/* Player card                                                         */
function PlayerCard({
  player,
  course,
  onChange,
  onRemove,
}: {
  player: Player
  course?: Course
  onChange: (p: Partial<Player>) => void
  onRemove: () => void
}) {
  const [open, setOpen] = useState(false)
  const fullName = `${player.firstName}${player.lastName ? ` ${player.lastName}` : ""}`.trim()
  const isOwner = player.kind === "owner"
  const hcpText = player.hcpFromProfile
    ? player.hcp != null
      ? String(player.hcp)
      : "fra profil"
    : player.hcp != null
      ? String(player.hcp)
      : "–"

  const tees = compatibleTees(course, player.gender)

  return (
    <div className="rounded-xl border border-[var(--nr-border)] bg-[var(--nr-surface)]">
      <div className="flex items-center gap-3 p-3">
        <Avatar first={player.firstName || "?"} last={player.lastName} />
        <div className="min-w-0 flex-1">
          <div className="flex flex-wrap items-center gap-1.5">
            <span className="text-sm font-semibold text-[var(--nr-ink)]">{fullName || "Ny spiller"}</span>
            {isOwner ? <Pill tone="accent">Deg · Eier</Pill> : null}
            {player.isGuest ? <Pill tone="neutral">Gjest</Pill> : null}
          </div>
          <p className="truncate text-xs text-[var(--nr-muted)]">
            Utslag: {teeName(course, player.teeId)} · HCP: {hcpText}
          </p>
        </div>
        <button
          type="button"
          onClick={() => setOpen((o) => !o)}
          aria-expanded={open}
          aria-label={open ? `Skjul redigering av ${fullName}` : `Rediger ${fullName}`}
          className="flex h-10 w-10 items-center justify-center rounded-lg border border-[var(--nr-border)] text-[var(--nr-muted)] transition-colors hover:bg-[var(--nr-surface-2)] focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-[var(--nr-accent-ring)]/40"
        >
          <ChevronDown className={cn("h-4 w-4 transition-transform", open && "rotate-180")} aria-hidden="true" />
        </button>
        {!isOwner ? (
          <button
            type="button"
            onClick={onRemove}
            aria-label={`Fjern ${fullName}`}
            className="flex h-10 w-10 items-center justify-center rounded-lg border border-[var(--nr-border)] text-[var(--nr-muted)] transition-colors hover:text-[var(--nr-danger)] focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-[var(--nr-accent-ring)]/40"
          >
            <X className="h-4 w-4" aria-hidden="true" />
          </button>
        ) : null}
      </div>

      {open ? (
        <div className="flex flex-col gap-4 border-t border-[var(--nr-border)] p-4">
          {player.isGuest ? (
            <>
              <div className="grid grid-cols-2 gap-3">
                <Field label="Fornavn" htmlFor={`${player.key}-first`}>
                  <TextInput
                    id={`${player.key}-first`}
                    value={player.firstName}
                    onChange={(e) => onChange({ firstName: e.target.value })}
                    invalid={player.firstName.trim() === ""}
                  />
                </Field>
                <Field label="Etternavn" optional htmlFor={`${player.key}-last`}>
                  <TextInput
                    id={`${player.key}-last`}
                    value={player.lastName}
                    onChange={(e) => onChange({ lastName: e.target.value })}
                  />
                </Field>
              </div>
              <Field label="Kjønn">
                <GenderChoice
                  value={player.gender ?? "mann"}
                  onChange={(g) => {
                    const stillOk = compatibleTees(course, g).some((t) => t.id === player.teeId)
                    onChange({ gender: g, teeId: stillOk ? player.teeId : compatibleTees(course, g)[0]?.id })
                  }}
                />
              </Field>
              <Field label="E-post" optional htmlFor={`${player.key}-email`}>
                <TextInput
                  id={`${player.key}-email`}
                  type="email"
                  value={player.email ?? ""}
                  onChange={(e) => onChange({ email: e.target.value })}
                />
              </Field>
            </>
          ) : null}

          <Field label="Utslag" htmlFor={`${player.key}-tee`}>
            <NativeSelect
              id={`${player.key}-tee`}
              value={player.teeId ?? ""}
              onChange={(e) => onChange({ teeId: e.target.value })}
            >
              <option value="">Velg utslag</option>
              {tees.map((t) => (
                <option key={t.id} value={t.id}>
                  {t.name}
                </option>
              ))}
            </NativeSelect>
          </Field>

          {player.isGuest ? (
            <Field label="HCP" optional htmlFor={`${player.key}-hcp`}>
              <TextInput
                id={`${player.key}-hcp`}
                inputMode="decimal"
                value={player.hcp != null ? String(player.hcp) : ""}
                onChange={(e) => {
                  const v = e.target.value
                  onChange({ hcp: v.trim() === "" ? null : Number.parseFloat(v.replace(",", ".")) })
                }}
                className="max-w-[10rem]"
              />
            </Field>
          ) : player.hcpFromProfile && !isOwner ? (
            // Redigerbar fra FØRSTE stund (2026-08-20 brukerfunn) -- var
            // tidligere en read-only visning ("hentes fra profilen"), som
            // tvang organisatoren til å legge til spilleren FØRST og
            // overstyre HCP-en senere via "Runde og spillere" (der
            // overstyring allerede fungerte, samme PATCH-felt). Forhånds-
            // utfylt med profilverdien; urørt betyr fortsatt "bruk
            // profilen", akkurat som før.
            <Field
              label="HCP"
              optional
              htmlFor={`${player.key}-hcp`}
              hint="Hentes fra spillerens profil dersom du lar feltet stå urørt."
            >
              <TextInput
                id={`${player.key}-hcp`}
                inputMode="decimal"
                placeholder={player.hcp == null ? "Henter fra profil…" : undefined}
                value={player.hcp != null ? String(player.hcp) : ""}
                onChange={(e) => {
                  const v = e.target.value
                  onChange({ hcp: v.trim() === "" ? null : Number.parseFloat(v.replace(",", ".")) })
                }}
                className="max-w-[10rem]"
              />
            </Field>
          ) : null}

          <Field label="Statistikk">
            <StatChoice value={player.statLevel} onChange={(s) => onChange({ statLevel: s })} />
          </Field>
        </div>
      ) : null}
    </div>
  )
}

/* ------------------------------------------------------------------ */
/* Legg til-panel (søk + gjest)                                        */
function AddPlayerPanel({
  course,
  defaultStat,
  existing,
  onCancel,
  onAdd,
}: {
  course?: Course
  defaultStat: StatLevel
  existing: Player[]
  onCancel: () => void
  onAdd: (p: Player) => void
}) {
  const [mode, setMode] = useState<"search" | "guest">("search")
  const [query, setQuery] = useState("")
  const debounced = useDebouncedValue(query, 250)
  const [results, setResults] = useState<Account[]>([])

  // gjesteskjema
  const [first, setFirst] = useState("")
  const [last, setLast] = useState("")
  const [email, setEmail] = useState("")
  const [gender, setGender] = useState<Gender>("mann")
  const [hcp, setHcp] = useState("")
  const [stat, setStat] = useState<StatLevel>(defaultStat)
  const [teeId, setTeeId] = useState<string | undefined>(() => compatibleTees(course, "mann")[0]?.id)
  const firstRef = useRef<HTMLInputElement>(null)

  useEffect(() => {
    if (mode === "guest") firstRef.current?.focus()
  }, [mode])

  const existingAccountIds = new Set(existing.map((p) => p.accountId).filter(Boolean))

  useEffect(() => {
    const q = debounced.trim()
    if (q.length < 2) {
      setResults([])
      return
    }
    let cancelled = false
    void searchAccounts(q).then((r) => {
      if (!cancelled) setResults(r.filter((a) => !existingAccountIds.has(a.id)))
    })
    return () => {
      cancelled = true
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [debounced])

  function switchToGuest() {
    const parts = query.trim().split(/\s+/)
    setFirst(parts[0] ?? "")
    setLast(parts.slice(1).join(" "))
    setMode("guest")
  }

  function addAccount(acc: Account) {
    onAdd({
      key: nextKey(),
      kind: "account",
      accountId: acc.id,
      firstName: acc.firstName,
      lastName: acc.lastName,
      gender: undefined, // ukjent klient-side inntil profilen lastes
      isGuest: false,
      hcp: acc.handicap,
      hcpFromProfile: true,
      teeId: course?.tees[0]?.id,
      statLevel: defaultStat,
    })
  }

  function addGuest() {
    if (first.trim() === "") return
    onAdd({
      key: nextKey(),
      kind: "guest",
      firstName: first.trim(),
      lastName: last.trim(),
      gender,
      isGuest: true,
      email: email.trim() || undefined,
      hcp: hcp.trim() === "" ? null : Number.parseFloat(hcp.replace(",", ".")),
      teeId,
      statLevel: stat,
    })
  }

  return (
    <div className="rounded-xl border border-[var(--nr-accent-ring)] bg-[var(--nr-surface)] p-4">
      <div className="mb-3 flex items-center justify-between">
        <h3 className="text-sm font-semibold text-[var(--nr-ink)]">Legg til medspiller</h3>
        <button
          type="button"
          onClick={onCancel}
          aria-label="Lukk"
          className="flex h-9 w-9 items-center justify-center rounded-lg text-[var(--nr-muted)] hover:bg-[var(--nr-surface-2)]"
        >
          <X className="h-4 w-4" aria-hidden="true" />
        </button>
      </div>

      {mode === "search" ? (
        <div className="flex flex-col gap-3">
          <Field label="Navn på medspilleren" htmlFor="add-search" hint="Skriv minst 2 tegn for å søke.">
            <div className="relative">
              <Search className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-[var(--nr-faint)]" aria-hidden="true" />
              <TextInput
                id="add-search"
                value={query}
                onChange={(e) => setQuery(e.target.value)}
                placeholder="Søk etter en konto…"
                className="pl-9"
                autoComplete="off"
              />
            </div>
          </Field>

          {debounced.trim().length >= 2 ? (
            results.length > 0 ? (
              <ul className="flex flex-col gap-2">
                {results.map((a) => (
                  <li key={a.id}>
                    <button
                      type="button"
                      onClick={() => addAccount(a)}
                      className="flex min-h-14 w-full items-center gap-3 rounded-lg border border-[var(--nr-border)] bg-[var(--nr-surface)] px-3 py-2 text-left transition-colors hover:border-[var(--nr-border-strong)] focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-[var(--nr-accent-ring)]/40"
                    >
                      <Avatar first={a.firstName} last={a.lastName} />
                      <span className="flex-1">
                        <span className="block text-sm font-medium text-[var(--nr-ink)]">{a.firstName} {a.lastName}</span>
                        <span className="block text-xs text-[var(--nr-muted)]">{a.handicap != null ? `HCP ${a.handicap}` : "Ingen HCP registrert"}</span>
                      </span>
                      <UserPlus className="h-4 w-4 text-[var(--nr-accent)]" aria-hidden="true" />
                    </button>
                  </li>
                ))}
              </ul>
            ) : (
              <p className="text-sm text-[var(--nr-muted)]">Ingen kontoer matcher søket.</p>
            )
          ) : null}

          <button
            type="button"
            onClick={switchToGuest}
            className="text-left text-[13px] font-medium text-[var(--nr-accent)] underline-offset-2 hover:underline"
          >
            Legg til uten konto (gjest)
          </button>
        </div>
      ) : (
        <GuestForm
          course={course}
          first={first}
          setFirst={setFirst}
          last={last}
          setLast={setLast}
          email={email}
          setEmail={setEmail}
          gender={gender}
          setGender={setGender}
          hcp={hcp}
          setHcp={setHcp}
          stat={stat}
          setStat={setStat}
          teeId={teeId}
          setTeeId={setTeeId}
          firstRef={firstRef}
          onBackToSearch={() => setMode("search")}
          onSubmit={addGuest}
        />
      )}
    </div>
  )
}

function GuestForm({
  course,
  first,
  setFirst,
  last,
  setLast,
  email,
  setEmail,
  gender,
  setGender,
  hcp,
  setHcp,
  stat,
  setStat,
  teeId,
  setTeeId,
  firstRef,
  onBackToSearch,
  onSubmit,
}: {
  course?: Course
  first: string
  setFirst: (v: string) => void
  last: string
  setLast: (v: string) => void
  email: string
  setEmail: (v: string) => void
  gender: Gender
  setGender: (v: Gender) => void
  hcp: string
  setHcp: (v: string) => void
  stat: StatLevel
  setStat: (v: StatLevel) => void
  teeId: string | undefined
  setTeeId: (v: string | undefined) => void
  firstRef: React.RefObject<HTMLInputElement | null>
  onBackToSearch: () => void
  onSubmit: () => void
}) {
  const tees = compatibleTees(course, gender)
  // kjent-gjest-oppslag på e-post (scoped til DENNE brukeren server-side)
  const debouncedEmail = useDebouncedValue(email, 350)
  const [match, setMatch] = useState<KnownGuest | null>(null)

  useEffect(() => {
    const e = debouncedEmail.trim()
    if (e.length < 5 || !e.includes("@")) {
      setMatch(null)
      return
    }
    let cancelled = false
    void lookupKnownGuest(e).then((g) => {
      if (!cancelled) setMatch(g)
    })
    return () => {
      cancelled = true
    }
  }, [debouncedEmail])

  return (
    <div className="flex flex-col gap-3">
      <button
        type="button"
        onClick={onBackToSearch}
        className="self-start text-[13px] font-medium text-[var(--nr-accent)] underline-offset-2 hover:underline"
      >
        ← Søk etter konto i stedet
      </button>

      <div className="grid grid-cols-2 gap-3">
        <Field label="Fornavn" htmlFor="g-first">
          <TextInput id="g-first" ref={firstRef} value={first} onChange={(e) => setFirst(e.target.value)} invalid={first.trim() === ""} />
        </Field>
        <Field label="Etternavn" optional htmlFor="g-last">
          <TextInput id="g-last" value={last} onChange={(e) => setLast(e.target.value)} />
        </Field>
      </div>

      <Field label="E-post" optional htmlFor="g-email">
        <TextInput id="g-email" type="email" value={email} onChange={(e) => setEmail(e.target.value)} placeholder="navn@example.com" />
      </Field>

      {match ? (
        <div className="flex items-start gap-3 rounded-lg border border-[var(--nr-accent-ring)] bg-[var(--nr-accent-soft)] p-3">
          <Sparkles className="mt-0.5 h-4 w-4 shrink-0 text-[var(--nr-accent)]" aria-hidden="true" />
          <div className="flex-1">
            <p className="text-[13px] text-[var(--nr-ink)]">
              Vi fant {match.firstName} {match.lastName} fra en tidligere runde du satte opp.
            </p>
            <button
              type="button"
              onClick={() => {
                setFirst(match.firstName)
                setLast(match.lastName)
                const matchedGender = match.gender === "m" ? "mann" : match.gender === "f" ? "kvinne" : null
                if (matchedGender) {
                  const stillOk = compatibleTees(course, matchedGender).some((t) => t.id === teeId)
                  setGender(matchedGender)
                  if (!stillOk) setTeeId(compatibleTees(course, matchedGender)[0]?.id)
                }
                if (match.hcp != null) setHcp(String(match.hcp))
              }}
              className="mt-1 text-[13px] font-semibold text-[var(--nr-accent)] underline-offset-2 hover:underline"
            >
              Fyll inn automatisk
            </button>
          </div>
        </div>
      ) : null}

      <Field label="Kjønn">
        <GenderChoice
          value={gender}
          onChange={(g) => {
            const stillOk = compatibleTees(course, g).some((t) => t.id === teeId)
            setGender(g)
            if (!stillOk) setTeeId(compatibleTees(course, g)[0]?.id)
          }}
        />
      </Field>

      <Field label="Utslag" htmlFor="g-tee">
        <NativeSelect id="g-tee" value={teeId ?? ""} onChange={(e) => setTeeId(e.target.value || undefined)}>
          <option value="">Velg utslag</option>
          {tees.map((t: Tee) => (
            <option key={t.id} value={t.id}>
              {t.name}
            </option>
          ))}
        </NativeSelect>
      </Field>

      <Field label="HCP" optional htmlFor="g-hcp">
        <TextInput
          id="g-hcp"
          inputMode="decimal"
          value={hcp}
          onChange={(e) => setHcp(e.target.value)}
          className="max-w-[10rem]"
        />
      </Field>

      <Field label="Statistikk for denne spilleren">
        <StatChoice value={stat} onChange={setStat} />
      </Field>

      <button
        type="button"
        onClick={onSubmit}
        disabled={first.trim() === ""}
        className="mt-1 inline-flex min-h-11 items-center justify-center rounded-lg bg-[var(--nr-accent)] px-5 text-sm font-semibold text-[var(--nr-accent-ink)] transition-colors hover:brightness-110 disabled:cursor-not-allowed disabled:opacity-40"
      >
        Legg til gjest
      </button>
    </div>
  )
}

/* ------------------------------------------------------------------ */
function GenderChoice({ value, onChange }: { value: Gender; onChange: (v: Gender) => void }) {
  return (
    <div className="flex gap-2">
      {GENDERS.map((g) => (
        <ToggleButton key={g.value} active={value === g.value} onClick={() => onChange(g.value)} className="flex-1">
          {g.label}
        </ToggleButton>
      ))}
    </div>
  )
}

function StatChoice({ value, onChange }: { value: StatLevel; onChange: (v: StatLevel) => void }) {
  return (
    <div className="flex gap-2">
      {STAT.map((s) => (
        <ToggleButton key={s.value} active={value === s.value} onClick={() => onChange(s.value)} className="flex-1">
          {s.label}
        </ToggleButton>
      ))}
    </div>
  )
}
