"use client"

// Kompakt hull-/utslag-editor for org-turneringsmodulen (2026-08-04) --
// "opprett manuell bane" der var frem til nå KUN et navnefelt (ingen vei til
// hull/par/hcp-indeks/utslag fantes i det hele tatt, POST /orgs/{id}/courses
// tok bare imot `{name}`). Speiler single-runde-modulens `OwnCreateStep`
// (new-round.tsx) i FUNKSJON, men i et kompakt, kort-innebygd formspråk som
// matcher resten av turneringsmodulens skjemaer (h-10/h-11, text-sm) i
// stedet for enkeltrunde-modulens store veiviser-stil.
//
// Ren UI + lokal validering -- kalleren avgjør hvor dataene faktisk
// persisteres (org-`course` via POST /orgs/{id}/courses, som nå valgfritt
// tar imot samme `holes`/`tees`-form i tillegg til navn), matcher
// prosjektets etablerte "hold komponenten dum"-adaptermønster.
//
// `CourseTemplatePicker` under er selve inngangspunktet brukt fra
// tournament-program.tsx/individual-tournament-detail.tsx: tilbyr "fra
// bunnen av", "TeeOff-bane som mal" og "offentlig custom-bane som mal"
// (søk mot GET /personal-courses -- allerede, litt overraskende, et
// PLATTFORM-OMFATTENDE bibliotek uansett org/bruker, se rounds.py).

import { useEffect, useState } from "react"
import { Plus, Trash2, X } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"

export type ApiCourseHole = { hole_number: number; par: number; stroke_index: number }
export type ApiCourseTeeRating = { gender: "m" | "f"; course_rating: number; slope_rating: number; par: number }
export type ApiCourseTee = { name: string; ratings: ApiCourseTeeRating[] }
export type CourseTemplateValues = { name: string; holes: ApiCourseHole[]; tees: ApiCourseTee[] }
export type ApiCourseSummary = { id: string; name: string }

function blankHoles(): ApiCourseHole[] {
  return Array.from({ length: 18 }, (_, i) => ({ hole_number: i + 1, par: 4, stroke_index: i + 1 }))
}

function blankTees(): ApiCourseTee[] {
  return [{ name: "", ratings: [{ gender: "m", course_rating: 70, slope_rating: 113, par: 72 }] }]
}

type TeeRow = {
  key: string
  name: string
  men: boolean
  women: boolean
  menRating: { courseRating: string; slope: string; par: string }
  womenRating: { courseRating: string; slope: string; par: string }
}

function teesToRows(tees: ApiCourseTee[]): TeeRow[] {
  return tees.map((t, i) => {
    const m = t.ratings.find((r) => r.gender === "m")
    const f = t.ratings.find((r) => r.gender === "f")
    return {
      key: `${i}-${t.name}`,
      name: t.name,
      men: !!m,
      women: !!f,
      menRating: m
        ? { courseRating: String(m.course_rating), slope: String(m.slope_rating), par: String(m.par) }
        : { courseRating: "", slope: "", par: "" },
      womenRating: f
        ? { courseRating: String(f.course_rating), slope: String(f.slope_rating), par: String(f.par) }
        : { courseRating: "", slope: "", par: "" },
    }
  })
}

/** Kompakt skjema: 18-hulls par/stroke-indeks-rutenett + utslag med rating
 * per kjønn. Forhåndsutfylt fra `initial` når banen opprettes som mal-basert
 * (fra TeeOff eller en offentlig custom-bane). */
export function CourseTemplateEditor({
  initial,
  submitLabel,
  submitting,
  error,
  onSubmit,
  onCancel,
}: {
  initial?: CourseTemplateValues
  submitLabel: string
  submitting: boolean
  error: string | null
  onSubmit: (values: CourseTemplateValues) => void
  onCancel: () => void
}) {
  const [name, setName] = useState(initial?.name ?? "")
  const [holes, setHoles] = useState<ApiCourseHole[]>(initial?.holes ?? blankHoles())
  const [tees, setTees] = useState<TeeRow[]>(teesToRows(initial?.tees ?? blankTees()))

  function updateHole(index: number, field: "par" | "stroke_index", value: number) {
    setHoles((prev) => prev.map((h, i) => (i === index ? { ...h, [field]: value } : h)))
  }
  function updateTee(key: string, patch: Partial<TeeRow>) {
    setTees((prev) => prev.map((t) => (t.key === key ? { ...t, ...patch } : t)))
  }
  function addTee() {
    setTees((prev) => [
      ...prev,
      { key: `new-${Date.now()}`, name: "", men: false, women: false, menRating: { courseRating: "", slope: "", par: "" }, womenRating: { courseRating: "", slope: "", par: "" } },
    ])
  }
  function removeTee(key: string) {
    setTees((prev) => (prev.length > 1 ? prev.filter((t) => t.key !== key) : prev))
  }

  const indexesValid = new Set(holes.map((h) => h.stroke_index)).size === 18
  const teesValid = tees.every(
    (t) =>
      t.name.trim() !== "" &&
      (t.men || t.women) &&
      (!t.men || (t.menRating.courseRating.trim() && t.menRating.slope.trim() && t.menRating.par.trim())) &&
      (!t.women || (t.womenRating.courseRating.trim() && t.womenRating.slope.trim() && t.womenRating.par.trim())),
  )
  const canSubmit = name.trim() !== "" && indexesValid && teesValid && !submitting

  // Bevisst IKKE et <form onSubmit>: denne komponenten rendres ofte inne i
  // et YTRE skjema (NewRoundForm/CreateSessionCard), og nestede <form>-
  // elementer er ugyldig HTML -- funnet ved en ekte scratch-verifisering
  // 2026-08-04 (submit-knappen submittet i praksis det ytre runde-/økt-
  // skjemaet i stedet, en reell side-navigasjon som vasket bort ?org=...
  // fra URL-en). Samme feilklasse/fiks som OfficialCourseSearch fra før.
  function handleSubmit() {
    if (!canSubmit) return
    const parseDecimal = (v: string) => Number(v.replace(",", "."))
    onSubmit({
      name: name.trim(),
      holes,
      tees: tees.map((t) => ({
        name: t.name.trim(),
        ratings: [
          ...(t.men
            ? [{ gender: "m" as const, course_rating: parseDecimal(t.menRating.courseRating), slope_rating: Number(t.menRating.slope), par: Number(t.menRating.par) }]
            : []),
          ...(t.women
            ? [{ gender: "f" as const, course_rating: parseDecimal(t.womenRating.courseRating), slope_rating: Number(t.womenRating.slope), par: Number(t.womenRating.par) }]
            : []),
        ],
      })),
    })
  }

  return (
    <div className="flex flex-col gap-4 rounded-2xl border border-border bg-background p-4">
      {error && <p className="text-sm font-medium text-destructive">{error}</p>}

      <div className="flex flex-col gap-1.5">
        <Label htmlFor="ct-name" className="text-xs font-semibold">
          Navn på banen
        </Label>
        <Input id="ct-name" autoFocus value={name} onChange={(e) => setName(e.target.value)} placeholder="F.eks. Hjemmebanen" className="h-10 rounded-xl text-sm" />
      </div>

      <div className="flex flex-col gap-2">
        <span className="text-xs font-semibold">Hull -- par og stroke-indeks</span>
        {!indexesValid && (
          <p role="alert" className="text-xs font-medium text-destructive">
            Hver stroke-indeks (1-18) må brukes nøyaktig én gang.
          </p>
        )}
        <div className="max-h-72 overflow-y-auto rounded-xl border border-border">
          <div className="grid grid-cols-[auto_1fr_1fr] items-center gap-2 border-b border-border bg-muted/60 px-3 py-2 text-xs font-bold uppercase tracking-wide text-muted-foreground">
            <span className="w-12">Hull</span>
            <span>Par</span>
            <span>SI</span>
          </div>
          {holes.map((h, index) => (
            <div key={h.hole_number} className="grid grid-cols-[auto_1fr_1fr] items-center gap-2 border-b border-border px-3 py-1.5 last:border-b-0">
              <span className="w-12 text-sm font-semibold text-foreground">{h.hole_number}</span>
              <select
                aria-label={`Par for hull ${h.hole_number}`}
                value={h.par}
                onChange={(e) => updateHole(index, "par", Number(e.target.value))}
                className="h-9 rounded-lg border border-border bg-card px-2 text-sm font-medium text-foreground outline-none"
              >
                {[3, 4, 5, 6].map((p) => (
                  <option key={p} value={p}>
                    {p}
                  </option>
                ))}
              </select>
              <select
                aria-label={`Stroke-indeks for hull ${h.hole_number}`}
                value={h.stroke_index}
                onChange={(e) => updateHole(index, "stroke_index", Number(e.target.value))}
                className="h-9 rounded-lg border border-border bg-card px-2 text-sm font-medium text-foreground outline-none"
              >
                {Array.from({ length: 18 }, (_, i) => i + 1).map((si) => (
                  <option key={si} value={si}>
                    {si}
                  </option>
                ))}
              </select>
            </div>
          ))}
        </div>
      </div>

      <div className="flex flex-col gap-3">
        <span className="text-xs font-semibold">Utslag</span>
        {tees.map((t, index) => (
          <div key={t.key} className="flex flex-col gap-3 rounded-xl border border-border bg-card p-3">
            <div className="flex items-end gap-2">
              <div className="flex flex-1 flex-col gap-1.5">
                <Label htmlFor={`ct-tee-${t.key}`} className="text-xs font-semibold">
                  Navn på utslag {index + 1}
                </Label>
                <Input id={`ct-tee-${t.key}`} value={t.name} onChange={(e) => updateTee(t.key, { name: e.target.value })} placeholder="F.eks. Gul" className="h-10 rounded-xl text-sm" />
              </div>
              {tees.length > 1 && (
                <Button type="button" variant="ghost" onClick={() => removeTee(t.key)} className="h-10 shrink-0 rounded-xl px-3 text-xs font-bold text-muted-foreground">
                  <Trash2 aria-hidden="true" className="size-4" />
                </Button>
              )}
            </div>
            <RatingRow
              label="Herre"
              enabled={t.men}
              rating={t.menRating}
              onToggle={(men) => updateTee(t.key, { men })}
              onChange={(menRating) => updateTee(t.key, { menRating })}
              idPrefix={`ct-men-${t.key}`}
            />
            <RatingRow
              label="Dame"
              enabled={t.women}
              rating={t.womenRating}
              onToggle={(women) => updateTee(t.key, { women })}
              onChange={(womenRating) => updateTee(t.key, { womenRating })}
              idPrefix={`ct-women-${t.key}`}
            />
          </div>
        ))}
        <Button type="button" variant="outline" onClick={addTee} className="h-10 self-start rounded-xl text-xs font-bold">
          <Plus aria-hidden="true" className="size-4" />
          Legg til utslag
        </Button>
      </div>

      <div className="flex gap-2">
        <Button type="button" onClick={handleSubmit} disabled={!canSubmit} className="h-11 flex-1 rounded-xl text-sm font-bold">
          {submitting ? "Lagrer…" : submitLabel}
        </Button>
        <Button type="button" variant="ghost" onClick={onCancel} className="h-11 rounded-xl text-sm font-bold text-muted-foreground">
          Avbryt
        </Button>
      </div>
    </div>
  )
}

function RatingRow({
  label,
  enabled,
  rating,
  onToggle,
  onChange,
  idPrefix,
}: {
  label: string
  enabled: boolean
  rating: { courseRating: string; slope: string; par: string }
  onToggle: (enabled: boolean) => void
  onChange: (rating: { courseRating: string; slope: string; par: string }) => void
  idPrefix: string
}) {
  return (
    <div className="flex flex-col gap-2 rounded-lg border border-border bg-background/60 p-2.5">
      <label className="flex items-center gap-2 text-xs font-semibold text-foreground">
        <input
          type="checkbox"
          checked={enabled}
          onChange={(e) => onToggle(e.target.checked)}
          className="size-4 shrink-0 accent-primary"
        />
        {label}-rating
      </label>
      {enabled && (
        <div className="grid grid-cols-3 gap-2">
          <Input
            aria-label={`${label} course rating`}
            inputMode="decimal"
            value={rating.courseRating}
            onChange={(e) => onChange({ ...rating, courseRating: e.target.value })}
            placeholder="CR"
            className="h-9 rounded-lg text-sm"
          />
          <Input
            aria-label={`${label} slope`}
            inputMode="numeric"
            value={rating.slope}
            onChange={(e) => onChange({ ...rating, slope: e.target.value })}
            placeholder="Slope"
            className="h-9 rounded-lg text-sm"
          />
          <Input
            aria-label={`${label} par`}
            inputMode="numeric"
            value={rating.par}
            onChange={(e) => onChange({ ...rating, par: e.target.value })}
            placeholder="Par"
            className="h-9 rounded-lg text-sm"
          />
        </div>
      )}
    </div>
  )
}

// ---------------------------------------------------------------------------
// Mal-velger: "fra bunnen av" / "TeeOff-bane som mal" / "offentlig custom-
// bane som mal". Brukt som selve "opprett bane"-inngangen i org-
// turneringsmodulen (erstatter det tidligere bare-navnefeltet).
// ---------------------------------------------------------------------------

type ApiPublicCourse = { id: string; name: string; is_mine: boolean; created_by_display_name: string }
type ApiPublicCourseDetail = {
  id: string
  name: string
  holes: ApiCourseHole[]
  full_tees: ApiCourseTee[]
}
type ApiOfficialFacility = { slug: string; name: string; city: string | null; county: string | null }
type ApiOfficialCourseOption = { teeoff_course_id: number; name: string; is_main_course: boolean }
type ApiOfficialTeeOption = { name: string; genders: ("m" | "f")[] }
type ApiOfficialCourseDetail = { id: number; name: string; holes: { hole_number: number; par: number; stroke_index: number }[]; tees: (ApiOfficialTeeOption & { ratings?: ApiCourseTeeRating[] })[] }

type PickerStep =
  | { kind: "choose" }
  | { kind: "official-search" }
  | { kind: "official-facility"; facility: ApiOfficialFacility }
  | { kind: "public-search" }
  | { kind: "editor"; initial?: CourseTemplateValues; templatePersonalCourseId?: string }

export function CourseTemplatePicker({
  organizationId,
  onCreated,
  onCancel,
}: {
  organizationId: string
  onCreated: (course: ApiCourseSummary) => void
  onCancel: () => void
}) {
  const [step, setStep] = useState<PickerStep>({ kind: "choose" })
  const [submitting, setSubmitting] = useState(false)
  const [error, setError] = useState<string | null>(null)

  async function submitCourse(values: CourseTemplateValues, templatePersonalCourseId?: string) {
    setSubmitting(true)
    setError(null)
    try {
      const res = await fetch(`/orgs/${organizationId}/courses`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        credentials: "include",
        body: JSON.stringify({ ...values, template_personal_course_id: templatePersonalCourseId ?? null }),
      })
      if (!res.ok) throw new Error(`create course: ${res.status}`)
      const created: ApiCourseSummary = await res.json()
      onCreated(created)
    } catch {
      setError("Klarte ikke å opprette banen. Sjekk at hull og utslag er fylt ut riktig.")
    } finally {
      setSubmitting(false)
    }
  }

  if (step.kind === "choose") {
    return (
      <div className="flex flex-col gap-2 rounded-2xl border border-border bg-background p-4">
        <span className="text-xs font-semibold">Opprett manuell bane</span>
        <div className="flex flex-col gap-2 sm:flex-row">
          <Button type="button" variant="outline" onClick={() => setStep({ kind: "editor" })} className="h-11 flex-1 rounded-xl text-sm font-bold">
            Fra bunnen av
          </Button>
          <Button type="button" variant="outline" onClick={() => setStep({ kind: "official-search" })} className="h-11 flex-1 rounded-xl text-sm font-bold">
            TeeOff-bane som mal
          </Button>
          <Button type="button" variant="outline" onClick={() => setStep({ kind: "public-search" })} className="h-11 flex-1 rounded-xl text-sm font-bold">
            Offentlig bane som mal
          </Button>
        </div>
        <Button type="button" variant="ghost" onClick={onCancel} className="h-9 self-start rounded-xl text-xs font-semibold text-muted-foreground">
          Avbryt
        </Button>
      </div>
    )
  }

  if (step.kind === "official-search") {
    return (
      <OfficialFacilitySearch
        organizationId={organizationId}
        onPickFacility={(facility) => setStep({ kind: "official-facility", facility })}
        onClose={() => setStep({ kind: "choose" })}
      />
    )
  }

  if (step.kind === "official-facility") {
    return (
      <OfficialCourseList
        organizationId={organizationId}
        facility={step.facility}
        onBack={() => setStep({ kind: "official-search" })}
        onPicked={(values) => setStep({ kind: "editor", initial: values })}
      />
    )
  }

  if (step.kind === "public-search") {
    return (
      <PublicCourseSearch
        onPickDirect={(values, sourceId) => submitCourse(values, sourceId)}
        onPickCustomize={(values, sourceId) => setStep({ kind: "editor", initial: values, templatePersonalCourseId: sourceId })}
        onClose={() => setStep({ kind: "choose" })}
      />
    )
  }

  return (
    <CourseTemplateEditor
      initial={step.initial}
      submitLabel="Opprett bane"
      submitting={submitting}
      error={error}
      onSubmit={(values) => submitCourse(values, step.templatePersonalCourseId)}
      onCancel={() => setStep({ kind: "choose" })}
    />
  )
}

function OfficialFacilitySearch({
  organizationId,
  onPickFacility,
  onClose,
}: {
  organizationId: string
  onPickFacility: (facility: ApiOfficialFacility) => void
  onClose: () => void
}) {
  const [query, setQuery] = useState("")
  const [facilities, setFacilities] = useState<ApiOfficialFacility[] | null>(null)
  const [searching, setSearching] = useState(false)
  const [error, setError] = useState<string | null>(null)

  async function runSearch() {
    setSearching(true)
    setError(null)
    try {
      const res = await fetch(`/orgs/${organizationId}/courses/official-search?q=${encodeURIComponent(query.trim())}`, { credentials: "include" })
      if (!res.ok) throw new Error(`search: ${res.status}`)
      setFacilities(await res.json())
    } catch {
      setError("Klarte ikke å søke i teeoff sine baner akkurat nå.")
      setFacilities([])
    } finally {
      setSearching(false)
    }
  }

  return (
    <div className="flex flex-col gap-3 rounded-2xl border border-border bg-background p-4">
      <div className="flex items-center justify-between gap-2">
        <span className="text-sm font-bold text-foreground">TeeOff-bane som mal</span>
        <Button type="button" variant="ghost" size="icon" onClick={onClose} className="size-8 rounded-lg text-muted-foreground" aria-label="Lukk">
          <X aria-hidden="true" className="size-4" />
        </Button>
      </div>
      {error && <p className="text-sm font-medium text-destructive">{error}</p>}
      <div className="flex items-center gap-2">
        <Input
          autoFocus
          placeholder="Søk anleggsnavn…"
          value={query}
          onChange={(e) => setQuery(e.target.value)}
          onKeyDown={(e) => {
            if (e.key === "Enter") {
              e.preventDefault()
              runSearch()
            }
          }}
          className="h-11 flex-1 rounded-xl text-base"
        />
        <Button type="button" onClick={() => runSearch()} disabled={searching} className="h-11 shrink-0 rounded-xl font-bold">
          {searching ? "Søker…" : "Søk"}
        </Button>
      </div>
      {facilities && (
        <ul className="flex max-h-56 flex-col overflow-auto rounded-xl border border-border">
          {facilities.map((f) => (
            <li key={f.slug} className="border-b border-border last:border-b-0">
              <button type="button" onClick={() => onPickFacility(f)} className="flex w-full flex-col px-4 py-2.5 text-left transition-colors hover:bg-accent/60">
                <span className="text-sm font-semibold text-foreground">{f.name}</span>
                {(f.city || f.county) && <span className="text-xs text-muted-foreground">{[f.city, f.county].filter(Boolean).join(", ")}</span>}
              </button>
            </li>
          ))}
          {facilities.length === 0 && <li className="px-4 py-3 text-center text-sm text-muted-foreground">Ingen treff.</li>}
        </ul>
      )}
    </div>
  )
}

function OfficialCourseList({
  organizationId,
  facility,
  onBack,
  onPicked,
}: {
  organizationId: string
  facility: ApiOfficialFacility
  onBack: () => void
  onPicked: (values: CourseTemplateValues) => void
}) {
  const [courses, setCourses] = useState<ApiOfficialCourseOption[] | null>(null)
  const [error, setError] = useState<string | null>(null)
  const [loadingCourseId, setLoadingCourseId] = useState<number | null>(null)

  useEffect(() => {
    let cancelled = false
    fetch(`/orgs/${organizationId}/courses/official-search/${facility.slug}`, { credentials: "include" })
      .then((res) => (res.ok ? res.json() : { courses: [] }))
      .then((detail: { courses: ApiOfficialCourseOption[] }) => {
        if (!cancelled) setCourses(detail.courses)
      })
      .catch(() => {
        if (!cancelled) setError("Klarte ikke å hente baner for dette anlegget.")
      })
    return () => {
      cancelled = true
    }
  }, [organizationId, facility.slug])

  async function pick(course: ApiOfficialCourseOption) {
    // Henter full bane-/utslagdata via samme offisiell-import-endepunkt som
    // "vanlig" import bruker -- men i STEDET for å lagre importen som en
    // ferdig org-bane, brukes svaret KUN til å forhåndsutfylle det
    // redigerbare skjemaet (ingen kobling til TeeOff bevares etterpå, se
    // migrasjon 054 sin kommentar om "engangs-kopi, ingen vedvarende
    // kobling"). Trygt å kalle -- import er idempotent (courses.py).
    setLoadingCourseId(course.teeoff_course_id)
    setError(null)
    try {
      const res = await fetch(`/orgs/${organizationId}/courses/official-import`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        credentials: "include",
        body: JSON.stringify({ facility_slug: facility.slug, teeoff_course_id: course.teeoff_course_id }),
      })
      if (!res.ok) throw new Error(`import: ${res.status}`)
      const imported: { id: string; name: string } = await res.json()
      const [holesRes, teesRes] = await Promise.all([
        fetch(`/orgs/${organizationId}/courses/${imported.id}/holes`, { credentials: "include" }),
        fetch(`/orgs/${organizationId}/courses/${imported.id}/tees`, { credentials: "include" }),
      ])
      const holes: ApiCourseHole[] = holesRes.ok ? await holesRes.json() : []
      const teesRaw: { name: string; ratings: ApiCourseTeeRating[] }[] = teesRes.ok ? await teesRes.json() : []
      onPicked({ name: imported.name, holes, tees: teesRaw.map((t) => ({ name: t.name, ratings: t.ratings })) })
    } catch {
      setError("Klarte ikke å hente banedata fra teeoff. Prøv igjen.")
    } finally {
      setLoadingCourseId(null)
    }
  }

  return (
    <div className="flex flex-col gap-3 rounded-2xl border border-border bg-background p-4">
      <button type="button" onClick={onBack} className="self-start text-sm font-semibold text-muted-foreground hover:text-foreground">
        ← {facility.name}
      </button>
      {error && <p className="text-sm font-medium text-destructive">{error}</p>}
      {courses === null ? (
        <p className="text-sm text-muted-foreground">Laster baner…</p>
      ) : (
        <ul className="flex flex-col overflow-hidden rounded-xl border border-border">
          {courses.map((c) => (
            <li key={c.teeoff_course_id} className="border-b border-border last:border-b-0">
              <button
                type="button"
                disabled={loadingCourseId !== null}
                onClick={() => pick(c)}
                className="flex w-full items-center justify-between px-4 py-2.5 text-left text-sm font-semibold text-foreground transition-colors hover:bg-accent/60 disabled:opacity-50"
              >
                {c.name}
                {loadingCourseId === c.teeoff_course_id && <span className="text-xs font-normal text-muted-foreground">Henter…</span>}
              </button>
            </li>
          ))}
          {courses.length === 0 && <li className="px-4 py-3 text-center text-sm text-muted-foreground">Ingen 18-hulls baner hos dette anlegget ennå.</li>}
        </ul>
      )}
    </div>
  )
}

function PublicCourseSearch({
  onPickDirect,
  onPickCustomize,
  onClose,
}: {
  onPickDirect: (values: CourseTemplateValues, sourcePersonalCourseId: string) => void
  onPickCustomize: (values: CourseTemplateValues, sourcePersonalCourseId: string) => void
  onClose: () => void
}) {
  const [query, setQuery] = useState("")
  const [results, setResults] = useState<ApiPublicCourse[]>([])
  const [loadingId, setLoadingId] = useState<string | null>(null)
  const [error, setError] = useState<string | null>(null)

  useEffect(() => {
    let cancelled = false
    const timer = setTimeout(() => {
      fetch(`/personal-courses?q=${encodeURIComponent(query.trim())}`, { credentials: "include" })
        .then((res) => (res.ok ? res.json() : []))
        .then((data: ApiPublicCourse[]) => {
          if (!cancelled) setResults(data)
        })
        .catch(() => {})
    }, 250)
    return () => {
      cancelled = true
      clearTimeout(timer)
    }
  }, [query])

  async function fetchDetail(course: ApiPublicCourse): Promise<CourseTemplateValues | null> {
    setLoadingId(course.id)
    setError(null)
    try {
      const res = await fetch(`/personal-courses/${course.id}`, { credentials: "include" })
      if (!res.ok) throw new Error(`detail: ${res.status}`)
      const detail: ApiPublicCourseDetail = await res.json()
      return { name: detail.name, holes: detail.holes, tees: detail.full_tees }
    } catch {
      setError("Klarte ikke å hente banedetaljer.")
      return null
    } finally {
      setLoadingId(null)
    }
  }

  return (
    <div className="flex flex-col gap-3 rounded-2xl border border-border bg-background p-4">
      <div className="flex items-center justify-between gap-2">
        <span className="text-sm font-bold text-foreground">Offentlig bane som mal</span>
        <Button type="button" variant="ghost" size="icon" onClick={onClose} className="size-8 rounded-lg text-muted-foreground" aria-label="Lukk">
          <X aria-hidden="true" className="size-4" />
        </Button>
      </div>
      {error && <p className="text-sm font-medium text-destructive">{error}</p>}
      <Input autoFocus value={query} onChange={(e) => setQuery(e.target.value)} placeholder="Søk etter banenavn…" className="h-11 rounded-xl text-sm" />
      <ul className="flex max-h-72 flex-col gap-2 overflow-auto">
        {results.map((c) => (
          <li key={c.id} className="flex flex-col gap-2 rounded-xl border border-border p-3">
            <div className="flex flex-col">
              <span className="text-sm font-semibold text-foreground">{c.name}</span>
              <span className="text-xs text-muted-foreground">{c.is_mine ? "Opprettet av deg" : `Opprettet av ${c.created_by_display_name}`}</span>
            </div>
            <div className="flex gap-2">
              <Button
                type="button"
                variant="outline"
                disabled={loadingId !== null}
                onClick={async () => {
                  const values = await fetchDetail(c)
                  if (values) onPickDirect(values, c.id)
                }}
                className="h-9 flex-1 rounded-lg text-xs font-bold"
              >
                Bruk direkte
              </Button>
              <Button
                type="button"
                variant="outline"
                disabled={loadingId !== null}
                onClick={async () => {
                  const values = await fetchDetail(c)
                  if (values) onPickCustomize(values, c.id)
                }}
                className="h-9 flex-1 rounded-lg text-xs font-bold"
              >
                Tilpass før bruk
              </Button>
            </div>
          </li>
        ))}
        {results.length === 0 && (
          <li className="px-3 py-4 text-center text-sm text-muted-foreground">
            {query.trim() ? `Ingen offentlige baner matcher «${query}».` : "Skriv for å søke."}
          </li>
        )}
      </ul>
    </div>
  )
}
