"use client"

// Opprett en frittstående runde (ADR-033). Presentasjon fra V0, datalag
// skrevet om fra mock til ekte søk/opprettelse/bekreftelse mot API-et.
// To bane-kilder: offisiell teeoff-bane (live oppslag, ADR-033 Beslutning C
// -- ingen lokal kopi lagres) eller en egendefinert bane (organisasjons-
// uavhengig katalog, søkbar på tvers av alle brukere).

import type React from "react"
import { useEffect, useMemo, useState } from "react"
import { useRouter, useSearchParams } from "next/navigation"
import Link from "next/link"
import {
  ArrowLeft,
  Building2,
  Check,
  Flag,
  MapPin,
  Pencil,
  Plus,
  Search,
  Trophy,
} from "lucide-react"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Switch } from "@/components/ui/switch"
import { Wordmark } from "@/components/wordmark"
import { cn } from "@/lib/utils"

// --- Types -----------------------------------------------------------------

type Rating = { courseRating: string; slope: string; par: string }

type Tee = {
  id: string
  name: string
  men: boolean
  women: boolean
  menRating?: Rating
  womenRating?: Rating
}

type Course = {
  id: string
  name: string
  tees: Tee[]
}

type OfficialClub = {
  id: string
  name: string
  location: string
  courses: Course[]
}

type Step =
  | "source"
  | "official-search"
  | "official-courses"
  | "own-search"
  | "own-create"
  | "confirm"

// Hvilken bane-kilde+id som faktisk skal sendes til /rounds -- Course-typen
// over (fra V0) bærer kun det UI-et trenger, ikke dette. Holdt separat i
// stedet for å presse det inn i Course, som er felles for begge kilder.
type CourseMeta =
  | { source: "teeoff"; facilitySlug: string; teeoffCourseId: number }
  | { source: "custom"; personalCourseId: string }

type Gender = "m" | "f"
type StatLevel = "strokes_only" | "strokes_and_putts" | "full"
// ADR-038/ADR-039 -- selvdeklarert spilleform. Ingen egen match-/skins-motor
// for frittstående runder, så dette taes brukerens ord for. Sider (for de
// to-sidede formatene) opprettes IKKE her -- det skjer i selve runden
// (POST .../sides), siden det krever at deltakerne allerede finnes.
type PlayFormat =
  | "stroke"
  | "match"
  | "stableford"
  | "skins"
  | "fourball"
  | "foursome"
  | "greensome"
  | "scramble_2"
  | "scramble_4"
type SkinsScoring = "net" | "gross"
type SkinsTieHandling = "carry" | "split"

// ADR-036 Beslutning B (fase 2, 2026-07-28) -- styrer KUN tredjeparts
// innsyn (venner/offentligheten), aldri en faktisk lagt-til medspiller
// (som alltid ser runden uansett). Trygg standard "private".
type VisibilityMode = "private" | "public" | "friends"

// Samme faste sett/rekkefølge som friends.py sin Category og
// friends.tsx sin CATEGORY_OPTIONS -- egen, lokal kopi (samme
// "liten duplisering fremfor cross-file-import"-mønster som FORMAT_LABELS
// ellers i appen).
const VISIBILITY_CATEGORY_OPTIONS = [
  { code: "spouse", label: "Make" },
  { code: "close_family", label: "Nær familie" },
  { code: "extended_family", label: "Storfamilie" },
  { code: "close_friends", label: "Nære venner" },
  { code: "golf_friends", label: "Golfvenner" },
  { code: "colleagues", label: "Kollegaer" },
  { code: "business", label: "Forretningsforbindelser" },
  { code: "classmates", label: "Studiekamerater" },
  { code: "acquaintances", label: "Perifere bekjente" },
  { code: "other", label: "Ymse" },
] as const

const PLAY_FORMAT_OPTIONS: { value: PlayFormat; label: string; desc: string }[] = [
  { value: "stroke", label: "Slagspill", desc: "Vanlig individuell runde." },
  { value: "stableford", label: "Stableford", desc: "Poeng per hull i stedet for slag -- kan plukke opp ved 0 poeng." },
  { value: "match", label: "Match", desc: "To sider, hull mot hull." },
  { value: "skins", label: "Skins", desc: "Hvert hull er en egen premie -- minst 3 spillere." },
  { value: "fourball", label: "Fourball", desc: "To mot to, beste ball per side." },
  { value: "foursome", label: "Foursome", desc: "To mot to, én delt ball, annenhver slår." },
  { value: "greensome", label: "Greensome", desc: "To mot to, begge slår ut, velger så én ball." },
  { value: "scramble_2", label: "Scramble (2)", desc: "To mot to, velger beste slag hver gang." },
  { value: "scramble_4", label: "Scramble (4)", desc: "Fire mot fire, velger beste slag hver gang." },
]

// --- API-typer ---------------------------------------------------------------

type ApiTeeOption = { name: string; genders: Gender[] }
type ApiFacility = { slug: string; name: string; city: string | null; county: string | null }
type ApiOfficialCourseOption = {
  teeoff_course_id: number
  name: string
  is_main_course: boolean
  tees: ApiTeeOption[]
}
type ApiPersonalCourse = { id: string; name: string }
type ApiPersonalCourseDetail = { id: string; name: string; tees: ApiTeeOption[] }

function apiTeesToTees(apiTees: ApiTeeOption[]): Tee[] {
  return apiTees.map((t, i) => ({
    id: `${t.name}-${i}`,
    name: t.name,
    men: t.genders.includes("m"),
    women: t.genders.includes("f"),
  }))
}

// --- Root component --------------------------------------------------------

export function NewRound() {
  const router = useRouter()
  const searchParams = useSearchParams()
  // Flere flighter i én "vanlig" runde (migrasjon 035) -- kommer fra
  // round-detail.tsx sin "Legg til en flight til"-handling. Rene primitiver
  // i URL-en (ikke et bane-oppslag) -- brukeren velger selv bane på nytt
  // for hver flight, men slipper å taste dato/starthull/spilleform igjen.
  const flightGroupId = searchParams.get("flightGroupId")
  const prefillPlayedAt = searchParams.get("playedAt") ?? undefined
  const prefillStartHole = searchParams.get("startHole")
  const prefillHoles = searchParams.get("holes")
  const prefillPlayFormat = searchParams.get("playFormat") as PlayFormat | null
  const [step, setStep] = useState<Step>("source")

  const [ownGender, setOwnGender] = useState<Gender | null>(null)
  const [loadingMe, setLoadingMe] = useState(true)

  // Official flow
  const [selectedClub, setSelectedClub] = useState<OfficialClub | null>(null)
  const [resolvingClub, setResolvingClub] = useState(false)

  // Chosen course carried into the confirm step (from any source), plus
  // which source/id it actually came from -- needed to build the /rounds
  // payload correctly.
  const [course, setCourse] = useState<Course | null>(null)
  const [courseMeta, setCourseMeta] = useState<CourseMeta | null>(null)

  useEffect(() => {
    let cancelled = false
    async function loadMe() {
      try {
        const res = await fetch("/auth/me", { credentials: "include" })
        if (res.status === 401) {
          router.replace("/")
          return
        }
        const data: { gender: Gender | null } = await res.json()
        if (!cancelled) setOwnGender(data.gender)
      } finally {
        if (!cancelled) setLoadingMe(false)
      }
    }
    void loadMe()
    return () => {
      cancelled = true
    }
  }, [router])

  function chooseCourse(next: Course, meta: CourseMeta) {
    setCourse(next)
    setCourseMeta(meta)
    setStep("confirm")
  }

  async function selectClub(club: OfficialClub) {
    setSelectedClub(club)
    setResolvingClub(true)
    try {
      const res = await fetch(`/rounds/official-search/${club.id}`, { credentials: "include" })
      if (!res.ok) throw new Error(`facility detail: ${res.status}`)
      const detail: { courses: ApiOfficialCourseOption[] } = await res.json()
      const withCourses: OfficialClub = {
        ...club,
        courses: detail.courses.map((c) => ({
          id: String(c.teeoff_course_id),
          name: c.name,
          tees: apiTeesToTees(c.tees),
        })),
      }
      setSelectedClub(withCourses)
      setStep("official-courses")
    } catch {
      setSelectedClub(null)
    } finally {
      setResolvingClub(false)
    }
  }

  function chooseOfficialCourse(officialCourse: Course) {
    if (!selectedClub) return
    chooseCourse(officialCourse, {
      source: "teeoff",
      facilitySlug: selectedClub.id,
      teeoffCourseId: Number(officialCourse.id),
    })
  }

  async function selectOwnCourse(picked: ApiPersonalCourse) {
    const res = await fetch(`/personal-courses/${picked.id}`, { credentials: "include" })
    if (!res.ok) return
    const detail: ApiPersonalCourseDetail = await res.json()
    chooseCourse(
      { id: detail.id, name: detail.name, tees: apiTeesToTees(detail.tees) },
      { source: "custom", personalCourseId: detail.id },
    )
  }

  function ownCourseCreated(created: { id: string; name: string; tees: Tee[] }) {
    chooseCourse(
      { id: created.id, name: created.name, tees: created.tees },
      { source: "custom", personalCourseId: created.id },
    )
  }

  async function submitRound(payload: {
    name: string
    teeName: string
    date: string
    startedAt: string | null
    startHole: number
    holes: 9 | 18
    statLevel: StatLevel
    playFormat: PlayFormat
    excludeFromHandicap: boolean
    skinsScoring: SkinsScoring | null
    skinsTieHandling: SkinsTieHandling | null
    visibilityMode: VisibilityMode
    visibleCategories: string[]
  }): Promise<{ id: string }> {
    if (!courseMeta) throw new Error("Mangler valgt bane")
    const shared = {
      tee_name: payload.teeName,
      name: payload.name || null,
      played_at: payload.date,
      started_at: payload.startedAt,
      start_hole: payload.startHole,
      holes_planned: payload.holes,
      stat_level: payload.statLevel,
      play_format: payload.playFormat,
      exclude_owner_from_handicap: payload.excludeFromHandicap,
      skins_scoring: payload.skinsScoring,
      skins_tie_handling: payload.skinsTieHandling,
      visibility_mode: payload.visibilityMode,
      visible_categories: payload.visibilityMode === "friends" ? payload.visibleCategories : [],
      flight_group_id: flightGroupId || undefined,
    }
    const body =
      courseMeta.source === "teeoff"
        ? {
            course_source: "teeoff",
            teeoff_facility_slug: courseMeta.facilitySlug,
            teeoff_course_id: courseMeta.teeoffCourseId,
            ...shared,
          }
        : {
            course_source: "custom",
            personal_course_id: courseMeta.personalCourseId,
            ...shared,
          }
    const res = await fetch("/rounds", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      credentials: "include",
      body: JSON.stringify(body),
    })
    if (!res.ok) throw new Error(`create round: ${res.status}`)
    return res.json()
  }

  return (
    <div className="flex min-h-[100dvh] flex-col bg-background">
      <header className="sticky top-0 z-10 border-b border-border bg-background/80 backdrop-blur">
        <div className="mx-auto flex w-full max-w-3xl items-center justify-between gap-4 px-5 py-4">
          <BackLink step={step} setStep={setStep} onExit={() => router.push("/my-rounds")} />
          <Wordmark compact />
        </div>
      </header>

      <main className="mx-auto w-full max-w-3xl flex-1 px-5 py-8 sm:py-10">
        {loadingMe ? (
          <p className="text-lg text-muted-foreground">Laster …</p>
        ) : !ownGender ? (
          <div className="rounded-2xl border border-border bg-card p-5 text-base text-muted-foreground">
            Profilen din mangler registrert kjønn, som trengs for å beregne banehandicap riktig.{" "}
            <Link href="/account" className="font-semibold text-primary underline underline-offset-2">
              Gå til kontoinnstillinger
            </Link>
            .
          </div>
        ) : (
          <>
            {step === "source" && (
              <SourceStep
                onOfficial={() => setStep("official-search")}
                onOwn={() => setStep("own-search")}
              />
            )}

            {step === "official-search" && (
              <OfficialSearchStep onSelectClub={selectClub} resolving={resolvingClub} />
            )}

            {step === "official-courses" && selectedClub && (
              <OfficialCoursesStep club={selectedClub} onSelectCourse={chooseOfficialCourse} />
            )}

            {step === "own-search" && (
              <OwnSearchStep onSelectCourse={selectOwnCourse} onCreate={() => setStep("own-create")} />
            )}

            {step === "own-create" && (
              <OwnCreateStep onCreated={ownCourseCreated} onCancel={() => setStep("own-search")} />
            )}

            {step === "confirm" && course && (
              <ConfirmStep
                course={course}
                ownGender={ownGender}
                onSubmit={submitRound}
                onCreated={(id) => router.replace(`/my-rounds/${id}`)}
                isAdditionalFlight={Boolean(flightGroupId)}
                defaultDate={prefillPlayedAt}
                defaultStartHole={prefillStartHole ?? undefined}
                defaultHoles={prefillHoles === "9" ? 9 : prefillHoles === "18" ? 18 : undefined}
                defaultPlayFormat={prefillPlayFormat ?? undefined}
              />
            )}
          </>
        )}
      </main>
    </div>
  )
}

// --- Back link -------------------------------------------------------------

function BackLink({
  step,
  setStep,
  onExit,
}: {
  step: Step
  setStep: (step: Step) => void
  onExit: () => void
}) {
  const config: Record<Step, { label: string; onClick: () => void }> = {
    source: { label: "Til egne runder", onClick: onExit },
    "official-search": { label: "Tilbake", onClick: () => setStep("source") },
    "official-courses": { label: "Tilbake til søk", onClick: () => setStep("official-search") },
    "own-search": { label: "Tilbake", onClick: () => setStep("source") },
    "own-create": { label: "Tilbake til søk", onClick: () => setStep("own-search") },
    confirm: { label: "Tilbake", onClick: () => setStep("source") },
  }

  const { label, onClick } = config[step]

  return (
    <button
      type="button"
      onClick={onClick}
      className="inline-flex min-h-[44px] items-center gap-2 rounded-xl px-2 py-2 text-base font-semibold text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background"
    >
      <ArrowLeft aria-hidden="true" className="size-5" />
      {label}
    </button>
  )
}

// --- Step header -----------------------------------------------------------

function StepHeader({ title, description }: { title: string; description: string }) {
  return (
    <div className="flex flex-col gap-2">
      <h1 className="text-3xl font-extrabold tracking-tight text-foreground text-balance">
        {title}
      </h1>
      <p className="max-w-prose text-lg leading-relaxed text-muted-foreground text-pretty">
        {description}
      </p>
    </div>
  )
}

// --- Step 1: source --------------------------------------------------------

function SourceStep({ onOfficial, onOwn }: { onOfficial: () => void; onOwn: () => void }) {
  return (
    <div className="flex flex-col gap-8">
      <StepHeader
        title="Ny runde"
        description="Velg hvor banen kommer fra for å komme i gang."
      />
      <div className="grid gap-4 sm:grid-cols-2">
        <SourceCard
          icon={<Trophy aria-hidden="true" className="size-7 text-primary" />}
          title="Offisiell bane"
          description="Søk opp klubben i det offisielle baneregisteret."
          onClick={onOfficial}
        />
        <SourceCard
          icon={<Pencil aria-hidden="true" className="size-7 text-primary" />}
          title="Egen bane"
          description="Banen finnes ikke i registeret – bruk en tidligere egendefinert bane eller opprett en ny."
          onClick={onOwn}
        />
      </div>
    </div>
  )
}

function SourceCard({
  icon,
  title,
  description,
  onClick,
}: {
  icon: React.ReactNode
  title: string
  description: string
  onClick: () => void
}) {
  return (
    <button
      type="button"
      onClick={onClick}
      className="flex min-h-[44px] flex-col items-start gap-4 rounded-3xl border border-border bg-card p-6 text-left shadow-md shadow-black/8 transition-colors hover:border-primary/50 hover:bg-accent/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background"
    >
      <div className="flex size-14 items-center justify-center rounded-2xl bg-primary/15">{icon}</div>
      <div className="flex flex-col gap-1.5">
        <h2 className="text-xl font-bold text-foreground">{title}</h2>
        <p className="text-base leading-relaxed text-muted-foreground text-pretty">{description}</p>
      </div>
    </button>
  )
}

// --- Step 2a: official search ----------------------------------------------

type ApiNearbyFacility = ApiFacility & { distance_km: number }

function NearbyClubs({
  onSelectClub,
  resolving,
}: {
  onSelectClub: (club: OfficialClub) => void
  resolving: boolean
}) {
  const [nearby, setNearby] = useState<ApiNearbyFacility[] | null>(null)

  useEffect(() => {
    if (!("geolocation" in navigator)) return
    let cancelled = false
    navigator.geolocation.getCurrentPosition(
      (position) => {
        if (cancelled) return
        const { latitude, longitude } = position.coords
        fetch(`/rounds/official-search/nearby?lat=${latitude}&lng=${longitude}&limit=5`, { credentials: "include" })
          .then((res) => (res.ok ? res.json() : null))
          .then((data: ApiNearbyFacility[] | null) => {
            if (!cancelled && data) setNearby(data)
          })
          .catch(() => {})
      },
      () => {
        // Avvist eller utilgjengelig -- stille no-op, dette er kun en
        // hjelp, ikke en forutsetning for å kunne søke.
      },
      { timeout: 8000 },
    )
    return () => {
      cancelled = true
    }
  }, [])

  if (!nearby || nearby.length === 0) return null

  return (
    <div className="flex flex-col gap-2">
      <span className="text-sm font-semibold text-muted-foreground">Nærmest deg</span>
      <ul className="flex flex-col overflow-hidden rounded-2xl border border-border">
        {nearby.map((facility, i) => (
          <li key={facility.slug} className="border-b border-border last:border-b-0">
            <button
              type="button"
              disabled={resolving}
              onClick={() =>
                onSelectClub({
                  id: facility.slug,
                  name: facility.name,
                  location: [facility.city, facility.county].filter(Boolean).join(", "),
                  courses: [],
                })
              }
              className={cn(
                "flex w-full items-center justify-between gap-3 px-4 py-3 text-left transition-colors hover:bg-accent/60",
                i === 0 && "bg-primary/5",
              )}
            >
              <div className="flex min-w-0 flex-col">
                <span className="flex items-center gap-2 text-base font-semibold text-foreground">
                  {facility.name}
                  {i === 0 && (
                    <span className="rounded-full bg-primary/15 px-2 py-0.5 text-xs font-bold text-primary">Nærmest</span>
                  )}
                </span>
                {(facility.city || facility.county) && (
                  <span className="truncate text-sm text-muted-foreground">
                    {[facility.city, facility.county].filter(Boolean).join(", ")}
                  </span>
                )}
              </div>
              <span className="shrink-0 text-sm font-semibold tabular-nums text-muted-foreground">
                {facility.distance_km < 1
                  ? `${Math.round(facility.distance_km * 1000)} m`
                  : `${facility.distance_km.toFixed(0)} km`}
              </span>
            </button>
          </li>
        ))}
      </ul>
    </div>
  )
}

function OfficialSearchStep({
  onSelectClub,
  resolving,
}: {
  onSelectClub: (club: OfficialClub) => void
  resolving: boolean
}) {
  const [query, setQuery] = useState("")
  const [results, setResults] = useState<ApiFacility[] | null>(null)
  const [searching, setSearching] = useState(false)
  const [error, setError] = useState<string | null>(null)

  async function handleSearch(e: React.FormEvent) {
    e.preventDefault()
    setSearching(true)
    setError(null)
    try {
      const res = await fetch(`/rounds/official-search?q=${encodeURIComponent(query.trim())}`, {
        credentials: "include",
      })
      if (!res.ok) throw new Error(`search: ${res.status}`)
      setResults(await res.json())
    } catch {
      setError("Klarte ikke å søke i baneregisteret akkurat nå.")
      setResults([])
    } finally {
      setSearching(false)
    }
  }

  return (
    <div className="flex flex-col gap-8">
      <StepHeader title="Offisiell bane" description="Søk opp klubben i baneregisteret." />

      <NearbyClubs onSelectClub={onSelectClub} resolving={resolving} />

      <form onSubmit={handleSearch} className="flex flex-col gap-3 sm:flex-row">
        <div className="relative flex-1">
          <Search
            aria-hidden="true"
            className="pointer-events-none absolute left-4 top-1/2 size-5 -translate-y-1/2 text-muted-foreground"
          />
          <Input
            value={query}
            onChange={(e) => setQuery(e.target.value)}
            placeholder="Søk etter klubbnavn…"
            aria-label="Klubbnavn"
            className="h-14 rounded-2xl pl-12 text-lg"
          />
        </div>
        <Button type="submit" size="lg" disabled={searching} className="h-14 gap-2 rounded-2xl px-8 text-base font-bold">
          <Search aria-hidden="true" className="size-5" />
          {searching ? "Søker…" : "Søk"}
        </Button>
      </form>

      {error && <p className="text-base font-medium text-destructive">{error}</p>}

      {results !== null && (
        <div className="flex flex-col gap-3">
          {results.length === 0 ? (
            <p className="rounded-2xl border border-border bg-muted/50 px-5 py-6 text-center text-base text-muted-foreground">
              Ingen klubber matcher «{query}». Prøv et annet søk.
            </p>
          ) : (
            <ul className="flex flex-col gap-3">
              {results.map((facility) => (
                <li key={facility.slug}>
                  <button
                    type="button"
                    disabled={resolving}
                    onClick={() =>
                      onSelectClub({
                        id: facility.slug,
                        name: facility.name,
                        location: [facility.city, facility.county].filter(Boolean).join(", "),
                        courses: [],
                      })
                    }
                    className="flex w-full items-center gap-4 rounded-2xl border border-border bg-card p-5 text-left shadow-md shadow-black/8 transition-colors hover:border-primary/50 hover:bg-accent/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:opacity-60"
                  >
                    <div className="flex size-12 shrink-0 items-center justify-center rounded-xl bg-primary/15">
                      <Building2 aria-hidden="true" className="size-6 text-primary" />
                    </div>
                    <div className="flex min-w-0 flex-col">
                      <span className="text-lg font-bold text-foreground">{facility.name}</span>
                      {facility.city || facility.county ? (
                        <span className="flex items-center gap-1.5 text-base text-muted-foreground">
                          <MapPin aria-hidden="true" className="size-4" />
                          {[facility.city, facility.county].filter(Boolean).join(", ")}
                        </span>
                      ) : null}
                    </div>
                  </button>
                </li>
              ))}
            </ul>
          )}
          {resolving && <p className="text-base text-muted-foreground">Henter baner …</p>}
        </div>
      )}
    </div>
  )
}

// --- Step 2a (cont): courses at club ---------------------------------------

function OfficialCoursesStep({
  club,
  onSelectCourse,
}: {
  club: OfficialClub
  onSelectCourse: (course: Course) => void
}) {
  return (
    <div className="flex flex-col gap-8">
      <StepHeader title={club.name} description="Velg hvilken bane du skal spille." />
      <ul className="flex flex-col gap-3">
        {club.courses.map((course) => (
          <li key={course.id}>
            <button
              type="button"
              onClick={() => onSelectCourse(course)}
              className="flex w-full items-center gap-4 rounded-2xl border border-border bg-card p-5 text-left shadow-md shadow-black/8 transition-colors hover:border-primary/50 hover:bg-accent/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background"
            >
              <div className="flex size-12 shrink-0 items-center justify-center rounded-xl bg-primary/15">
                <Flag aria-hidden="true" className="size-6 text-primary" />
              </div>
              <div className="flex min-w-0 flex-col">
                <span className="text-lg font-bold text-foreground">{course.name}</span>
                <span className="text-base text-muted-foreground">{course.tees.length} utslag</span>
              </div>
            </button>
          </li>
        ))}
        {club.courses.length === 0 && (
          <li className="rounded-2xl border border-border bg-muted/50 px-5 py-6 text-center text-base text-muted-foreground">
            Ingen 18-hulls baner registrert hos dette anlegget ennå.
          </li>
        )}
      </ul>
    </div>
  )
}

// --- Step 2b: own course search --------------------------------------------

function OwnSearchStep({
  onSelectCourse,
  onCreate,
}: {
  onSelectCourse: (course: ApiPersonalCourse) => void
  onCreate: () => void
}) {
  const [query, setQuery] = useState("")
  const [results, setResults] = useState<ApiPersonalCourse[]>([])
  const [error, setError] = useState<string | null>(null)

  useEffect(() => {
    let cancelled = false
    const timer = setTimeout(async () => {
      try {
        const res = await fetch(`/personal-courses?q=${encodeURIComponent(query.trim())}`, {
          credentials: "include",
        })
        if (!res.ok) throw new Error(`search: ${res.status}`)
        const data: ApiPersonalCourse[] = await res.json()
        if (!cancelled) setResults(data)
      } catch {
        if (!cancelled) setError("Klarte ikke å søke i egendefinerte baner akkurat nå.")
      }
    }, 250)
    return () => {
      cancelled = true
      clearTimeout(timer)
    }
  }, [query])

  return (
    <div className="flex flex-col gap-8">
      <StepHeader
        title="Egen bane"
        description="Søk opp en tidligere egendefinert bane, eller opprett en ny."
      />

      {error && <p className="text-base font-medium text-destructive">{error}</p>}

      <div className="relative">
        <Search
          aria-hidden="true"
          className="pointer-events-none absolute left-4 top-1/2 size-5 -translate-y-1/2 text-muted-foreground"
        />
        <Input
          autoFocus
          value={query}
          onChange={(e) => setQuery(e.target.value)}
          placeholder="Søk etter banenavn…"
          aria-label="Banenavn"
          className="h-14 rounded-2xl pl-12 text-lg"
        />
      </div>

      {results.length > 0 && (
        <ul className="flex flex-col gap-3">
          {results.map((course) => (
            <li key={course.id}>
              <button
                type="button"
                onClick={() => onSelectCourse(course)}
                className="flex w-full items-center gap-4 rounded-2xl border border-border bg-card p-5 text-left shadow-md shadow-black/8 transition-colors hover:border-primary/50 hover:bg-accent/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background"
              >
                <div className="flex size-12 shrink-0 items-center justify-center rounded-xl bg-primary/15">
                  <Flag aria-hidden="true" className="size-6 text-primary" />
                </div>
                <div className="flex min-w-0 flex-col">
                  <span className="text-lg font-bold text-foreground">{course.name}</span>
                </div>
              </button>
            </li>
          ))}
        </ul>
      )}

      {results.length === 0 && (
        <p className="rounded-2xl border border-border bg-muted/50 px-5 py-6 text-center text-base text-muted-foreground">
          {query.trim() ? `Ingen egne baner matcher «${query}».` : "Skriv for å søke, eller opprett en ny bane under."}
        </p>
      )}

      <button
        type="button"
        onClick={onCreate}
        className="flex min-h-[44px] items-center justify-center gap-2 rounded-2xl border-2 border-dashed border-border bg-card/40 px-6 py-5 text-lg font-bold text-foreground transition-colors hover:border-primary/60 hover:bg-accent/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background"
      >
        <Plus aria-hidden="true" className="size-5" />
        Opprett ny bane
      </button>
    </div>
  )
}

// --- Step 2b (cont): create course -----------------------------------------

function emptyHoles() {
  return Array.from({ length: 18 }, (_, i) => ({
    hole: i + 1,
    par: "4",
    strokeIndex: String(i + 1),
  }))
}

function parseDecimal(value: string): number {
  return Number(value.replace(",", "."))
}

function OwnCreateStep({
  onCreated,
  onCancel,
}: {
  onCreated: (course: { id: string; name: string; tees: Tee[] }) => void
  onCancel: () => void
}) {
  const [name, setName] = useState("")
  const [holes, setHoles] = useState(emptyHoles)
  const [tees, setTees] = useState<Tee[]>([
    { id: `nt-${Date.now()}`, name: "", men: true, women: false },
  ])
  const [submitting, setSubmitting] = useState(false)
  const [error, setError] = useState<string | null>(null)

  function updateHole(index: number, field: "par" | "strokeIndex", value: string) {
    setHoles((prev) => prev.map((h, i) => (i === index ? { ...h, [field]: value } : h)))
  }

  function updateTee(id: string, patch: Partial<Tee>) {
    setTees((prev) => prev.map((t) => (t.id === id ? { ...t, ...patch } : t)))
  }

  function addTee() {
    setTees((prev) => [...prev, { id: `nt-${Date.now()}`, name: "", men: false, women: false }])
  }

  function removeTee(id: string) {
    setTees((prev) => (prev.length > 1 ? prev.filter((t) => t.id !== id) : prev))
  }

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

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault()
    if (!canSubmit) return
    setSubmitting(true)
    setError(null)
    try {
      const body = {
        name: name.trim(),
        holes: holes.map((h) => ({
          hole_number: h.hole,
          par: Number(h.par),
          stroke_index: Number(h.strokeIndex),
        })),
        tees: tees.map((t) => ({
          name: t.name.trim(),
          ratings: [
            ...(t.men && t.menRating
              ? [{ gender: "m", course_rating: parseDecimal(t.menRating.courseRating), slope_rating: Number(t.menRating.slope), par: Number(t.menRating.par) }]
              : []),
            ...(t.women && t.womenRating
              ? [{ gender: "f", course_rating: parseDecimal(t.womenRating.courseRating), slope_rating: Number(t.womenRating.slope), par: Number(t.womenRating.par) }]
              : []),
          ],
        })),
      }
      const res = await fetch("/personal-courses", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        credentials: "include",
        body: JSON.stringify(body),
      })
      if (!res.ok) throw new Error(`create: ${res.status}`)
      const created: { id: string; name: string } = await res.json()
      onCreated({ id: created.id, name: created.name, tees: tees.map((t) => ({ ...t, name: t.name.trim() })) })
    } catch {
      setError("Klarte ikke å opprette banen. Sjekk at hull og utslag er fylt ut riktig.")
    } finally {
      setSubmitting(false)
    }
  }

  return (
    <form onSubmit={handleSubmit} className="flex flex-col gap-8">
      <StepHeader title="Opprett ny bane" description="Fyll inn banedata. Du kan endre detaljene senere." />

      {error && <p className="text-base font-medium text-destructive">{error}</p>}

      {/* Name */}
      <div className="flex flex-col gap-2">
        <Label htmlFor="course-name" className="text-base font-semibold">
          Navn på banen
        </Label>
        <Input
          id="course-name"
          value={name}
          onChange={(e) => setName(e.target.value)}
          placeholder="F.eks. Hyttebanen"
          className="h-14 rounded-2xl text-lg"
        />
      </div>

      {/* Holes */}
      <div className="flex flex-col gap-3">
        <div className="flex flex-col gap-1">
          <h2 className="text-xl font-bold text-foreground">Hull</h2>
          <p className="text-base text-muted-foreground">Sett par og stroke-indeks for hvert hull.</p>
        </div>
        {!indexesValid && (
          <p role="alert" className="text-base font-medium text-destructive">
            Hver stroke-indeks (1–18) må brukes nøyaktig én gang.
          </p>
        )}
        <div className="overflow-hidden rounded-2xl border border-border">
          <div className="grid grid-cols-[auto_1fr_1fr] items-center gap-3 border-b border-border bg-muted/60 px-4 py-3 text-sm font-bold uppercase tracking-wide text-muted-foreground">
            <span className="w-16">Hull</span>
            <span>Par</span>
            <span>Stroke-indeks</span>
          </div>
          <ul>
            {holes.map((h, index) => (
              <li
                key={h.hole}
                className="grid grid-cols-[auto_1fr_1fr] items-center gap-3 border-b border-border px-4 py-2.5 last:border-b-0"
              >
                <span className="w-16 text-base font-semibold text-foreground">Hull {h.hole}</span>
                <select
                  aria-label={`Par for hull ${h.hole}`}
                  value={h.par}
                  onChange={(e) => updateHole(index, "par", e.target.value)}
                  className="h-12 rounded-xl border border-input bg-background px-3 text-base font-semibold text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
                >
                  {[3, 4, 5, 6].map((p) => (
                    <option key={p} value={String(p)}>
                      Par {p}
                    </option>
                  ))}
                </select>
                <select
                  aria-label={`Stroke-indeks for hull ${h.hole}`}
                  value={h.strokeIndex}
                  onChange={(e) => updateHole(index, "strokeIndex", e.target.value)}
                  className="h-12 rounded-xl border border-input bg-background px-3 text-base font-semibold text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
                >
                  {Array.from({ length: 18 }, (_, i) => i + 1).map((si) => (
                    <option key={si} value={String(si)}>
                      {si}
                    </option>
                  ))}
                </select>
              </li>
            ))}
          </ul>
        </div>
      </div>

      {/* Tees */}
      <div className="flex flex-col gap-4">
        <div className="flex flex-col gap-1">
          <h2 className="text-xl font-bold text-foreground">Utslag</h2>
          <p className="text-base text-muted-foreground">Legg til ett eller flere utslag med rating.</p>
        </div>

        {tees.map((t, index) => (
          <TeeEditor
            key={t.id}
            tee={t}
            index={index}
            canRemove={tees.length > 1}
            onChange={(patch) => updateTee(t.id, patch)}
            onRemove={() => removeTee(t.id)}
          />
        ))}

        <button
          type="button"
          onClick={addTee}
          className="flex min-h-[44px] items-center justify-center gap-2 rounded-2xl border-2 border-dashed border-border bg-card/40 px-6 py-4 text-base font-bold text-foreground transition-colors hover:border-primary/60 hover:bg-accent/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background"
        >
          <Plus aria-hidden="true" className="size-5" />
          Legg til utslag
        </button>
      </div>

      <div className="flex flex-col gap-3 sm:flex-row-reverse">
        <Button
          type="submit"
          size="lg"
          disabled={!canSubmit}
          className="h-14 flex-1 rounded-2xl text-lg font-bold shadow-sm"
        >
          {submitting ? "Oppretter…" : "Opprett bane og fortsett"}
        </Button>
        <Button
          type="button"
          variant="ghost"
          size="lg"
          onClick={onCancel}
          className="h-14 rounded-2xl px-8 text-base font-semibold"
        >
          Avbryt
        </Button>
      </div>
    </form>
  )
}

function TeeEditor({
  tee,
  index,
  canRemove,
  onChange,
  onRemove,
}: {
  tee: Tee
  index: number
  canRemove: boolean
  onChange: (patch: Partial<Tee>) => void
  onRemove: () => void
}) {
  return (
    <div className="flex flex-col gap-4 rounded-2xl border border-border bg-card p-5 shadow-md shadow-black/8">
      <div className="flex items-end gap-3">
        <div className="flex flex-1 flex-col gap-2">
          <Label htmlFor={`tee-name-${tee.id}`} className="text-base font-semibold">
            Navn på utslag {index + 1}
          </Label>
          <Input
            id={`tee-name-${tee.id}`}
            value={tee.name}
            onChange={(e) => onChange({ name: e.target.value })}
            placeholder="F.eks. Gul"
            className="h-12 rounded-xl text-base"
          />
        </div>
        {canRemove && (
          <Button type="button" variant="outline" onClick={onRemove} className="h-12 rounded-xl px-4 text-base font-semibold">
            Fjern
          </Button>
        )}
      </div>

      <RatingToggle
        label="Herre-rating"
        enabled={tee.men}
        rating={tee.menRating}
        onToggle={(men) =>
          onChange({ men, menRating: men ? tee.menRating ?? { courseRating: "", slope: "", par: "" } : tee.menRating })
        }
        onRatingChange={(menRating) => onChange({ menRating })}
        idPrefix={`men-${tee.id}`}
      />
      <RatingToggle
        label="Dame-rating"
        enabled={tee.women}
        rating={tee.womenRating}
        onToggle={(women) =>
          onChange({ women, womenRating: women ? tee.womenRating ?? { courseRating: "", slope: "", par: "" } : tee.womenRating })
        }
        onRatingChange={(womenRating) => onChange({ womenRating })}
        idPrefix={`women-${tee.id}`}
      />
    </div>
  )
}

function RatingToggle({
  label,
  enabled,
  rating,
  onToggle,
  onRatingChange,
  idPrefix,
}: {
  label: string
  enabled: boolean
  rating?: Rating
  onToggle: (enabled: boolean) => void
  onRatingChange: (rating: Rating) => void
  idPrefix: string
}) {
  const current = rating ?? { courseRating: "", slope: "", par: "" }

  function update(field: keyof Rating, value: string) {
    onRatingChange({ ...current, [field]: value })
  }

  return (
    <div className="flex flex-col gap-3 rounded-xl border border-border bg-background/60 p-4">
      <div className="flex items-center justify-between gap-4">
        <Label htmlFor={idPrefix} className="text-base font-semibold text-foreground">
          {label}
        </Label>
        <Switch id={idPrefix} checked={enabled} onCheckedChange={onToggle} />
      </div>
      {enabled && (
        <div className="grid grid-cols-3 gap-3">
          <div className="flex flex-col gap-1.5">
            <Label htmlFor={`${idPrefix}-cr`} className="text-sm font-medium text-muted-foreground">
              Course Rating
            </Label>
            <Input
              id={`${idPrefix}-cr`}
              inputMode="decimal"
              value={current.courseRating}
              onChange={(e) => update("courseRating", e.target.value)}
              placeholder="71,2"
              className="h-12 rounded-xl text-base"
            />
          </div>
          <div className="flex flex-col gap-1.5">
            <Label htmlFor={`${idPrefix}-slope`} className="text-sm font-medium text-muted-foreground">
              Slope
            </Label>
            <Input
              id={`${idPrefix}-slope`}
              inputMode="numeric"
              value={current.slope}
              onChange={(e) => update("slope", e.target.value)}
              placeholder="132"
              className="h-12 rounded-xl text-base"
            />
          </div>
          <div className="flex flex-col gap-1.5">
            <Label htmlFor={`${idPrefix}-par`} className="text-sm font-medium text-muted-foreground">
              Par
            </Label>
            <Input
              id={`${idPrefix}-par`}
              inputMode="numeric"
              value={current.par}
              onChange={(e) => update("par", e.target.value)}
              placeholder="72"
              className="h-12 rounded-xl text-base"
            />
          </div>
        </div>
      )}
    </div>
  )
}

// --- Step 3: confirm -------------------------------------------------------

function todayIso() {
  const now = new Date()
  const offset = now.getTimezoneOffset()
  const local = new Date(now.getTime() - offset * 60 * 1000)
  return local.toISOString().slice(0, 10)
}

function ConfirmStep({
  course,
  ownGender,
  onSubmit,
  onCreated,
  isAdditionalFlight = false,
  defaultDate,
  defaultStartHole,
  defaultHoles,
  defaultPlayFormat,
}: {
  course: Course
  ownGender: Gender
  onSubmit: (payload: {
    name: string
    teeName: string
    date: string
    startedAt: string | null
    startHole: number
    holes: 9 | 18
    statLevel: StatLevel
    playFormat: PlayFormat
    excludeFromHandicap: boolean
    skinsScoring: SkinsScoring | null
    skinsTieHandling: SkinsTieHandling | null
    visibilityMode: VisibilityMode
    visibleCategories: string[]
  }) => Promise<{ id: string }>
  onCreated: (roundId: string) => void
  // Flere flighter (migrasjon 035) -- satt av round-detail.tsx sin
  // "Legg til en flight til" via URL-parametre, se NewRound() over.
  isAdditionalFlight?: boolean
  defaultDate?: string
  defaultStartHole?: string
  defaultHoles?: 9 | 18
  defaultPlayFormat?: PlayFormat
}) {
  const compatibleTees = course.tees.filter((t) => (ownGender === "m" ? t.men : t.women))
  const [teeId, setTeeId] = useState(compatibleTees[0]?.id ?? "")
  const [name, setName] = useState("")
  const [date, setDate] = useState(defaultDate ?? todayIso)
  const [teeTime, setTeeTime] = useState("")
  const [startHole, setStartHole] = useState(defaultStartHole ?? "1")
  const [holes, setHoles] = useState<9 | 18>(defaultHoles ?? 18)
  const [statLevel, setStatLevel] = useState<StatLevel>("strokes_only")
  const [playFormat, setPlayFormat] = useState<PlayFormat>(defaultPlayFormat ?? "stroke")
  const [excludeFromHandicap, setExcludeFromHandicap] = useState(false)
  // ADR-039 Beslutning D -- kun meningsfullt (og påkrevd av backend) for
  // play_format="skins". Fornuftige forhåndsvalg, begge overstyrbare.
  const [skinsScoring, setSkinsScoring] = useState<SkinsScoring>("net")
  const [skinsTieHandling, setSkinsTieHandling] = useState<SkinsTieHandling>("carry")
  // ADR-036 Beslutning B (fase 2, 2026-07-28) -- trygg standard "private".
  const [visibilityMode, setVisibilityMode] = useState<VisibilityMode>("private")
  // Alle forhåndsvalgt (2026-07-29, presisert av bruker: "man må heller
  // velge bort") -- kun brukt/sendt når visibilityMode faktisk er
  // "friends", så det er trygt at dette alltid starter fullt uansett.
  const [visibleCategories, setVisibleCategories] = useState<string[]>(VISIBILITY_CATEGORY_OPTIONS.map((c) => c.code))
  const [submitting, setSubmitting] = useState(false)
  const [error, setError] = useState<string | null>(null)

  function choosePlayFormat(next: PlayFormat) {
    setPlayFormat(next)
    // ADR-038 Beslutning D -- foreslå (ikke tving) eksklusjon når match
    // velges. De andre formatene har egne HCP-regler (ADR-039 Beslutning E)
    // som ikke bruker dette feltet -- nullstill det da for å unngå et
    // misvisende forhåndsvalg som likevel ikke sendes videre meningsfullt.
    setExcludeFromHandicap(next === "match")
  }

  const selectedTee = compatibleTees.find((t) => t.id === teeId)
  // ADR-039 Beslutning A -- match/fourball/foursome/greensome/scramble
  // krever sider, opprettet ETTERPÅ inne i selve runden (deltakerne må
  // finnes først). Vises som en forklarende note her, ikke et skjema.
  const needsSidesSetup = playFormat !== "stroke" && playFormat !== "stableford" && playFormat !== "skins"

  async function handleStart() {
    if (!selectedTee) return
    setSubmitting(true)
    setError(null)
    try {
      // Utslagstid er valgfritt -- kun dato er påkrevd. Kombinerer dato+
      // klokkeslett til et ekte tidspunkt (nettleserens lokale tidssone,
      // konvertert til UTC av toISOString()) kun når klokkeslett er satt.
      const startedAt = teeTime ? new Date(`${date}T${teeTime}`).toISOString() : null
      const created = await onSubmit({
        name: name.trim(),
        teeName: selectedTee.name,
        date,
        startedAt,
        startHole: Number(startHole),
        holes,
        statLevel,
        playFormat,
        excludeFromHandicap,
        skinsScoring: playFormat === "skins" ? skinsScoring : null,
        skinsTieHandling: playFormat === "skins" ? skinsTieHandling : null,
        visibilityMode,
        visibleCategories,
      })
      onCreated(created.id)
    } catch {
      setError("Klarte ikke å opprette runden. Prøv igjen.")
      setSubmitting(false)
    }
  }

  return (
    <div className="flex flex-col gap-8">
      <StepHeader title="Bekreft og fullfør" description="Sjekk detaljene før du starter runden." />

      {isAdditionalFlight && (
        <p className="rounded-2xl border border-dashed border-primary/40 bg-primary/5 px-4 py-3 text-sm font-semibold text-foreground">
          Du setter opp enda en flight i samme oppsett -- dato, starthull, hullantall og spilleform er
          forhåndsutfylt fra den første flighten, men kan endres.
        </p>
      )}

      {/* Course */}
      <div className="flex items-center gap-4 rounded-2xl border border-border bg-card p-5 shadow-md shadow-black/8">
        <div className="flex size-12 shrink-0 items-center justify-center rounded-xl bg-primary/15">
          <Flag aria-hidden="true" className="size-6 text-primary" />
        </div>
        <div className="flex flex-col">
          <span className="text-sm font-semibold uppercase tracking-wide text-muted-foreground">Valgt bane</span>
          <span className="text-lg font-bold text-foreground">{course.name}</span>
        </div>
      </div>

      {error && <p className="text-base font-medium text-destructive">{error}</p>}

      {/* Round name */}
      <div className="flex flex-col gap-2">
        <Label htmlFor="round-name" className="text-base font-semibold">
          Navn på runden <span className="font-normal text-muted-foreground">(valgfritt)</span>
        </Label>
        <Input
          id="round-name"
          value={name}
          onChange={(e) => setName(e.target.value)}
          placeholder={course.name}
          maxLength={200}
          className="h-14 rounded-2xl text-lg"
        />
      </div>

      {/* Tee */}
      {compatibleTees.length === 0 ? (
        <p role="alert" className="text-base font-medium text-destructive">
          Denne banen har ingen registrert rating for ditt kjønn på noe utslag -- HCP-sporing er
          ikke mulig for denne runden. Velg en annen bane, eller fullfør profilen din på nytt.
        </p>
      ) : (
        <fieldset className="flex flex-col gap-3">
          <legend className="mb-1 text-base font-semibold text-foreground">Utslag</legend>
          <div className="flex flex-wrap gap-2">
            {compatibleTees.map((t) => (
              <button
                key={t.id}
                type="button"
                onClick={() => setTeeId(t.id)}
                aria-pressed={teeId === t.id}
                className={cn(
                  "inline-flex min-h-[44px] items-center gap-2 rounded-2xl border px-5 py-2.5 text-base font-semibold transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
                  teeId === t.id
                    ? "border-primary bg-primary/10 text-foreground"
                    : "border-border bg-card text-muted-foreground hover:bg-accent/50 hover:text-foreground",
                )}
              >
                {teeId === t.id && <Check aria-hidden="true" className="size-4 text-primary" />}
                {t.name || "Uten navn"}
              </button>
            ))}
          </div>
        </fieldset>
      )}

      {/* Date + tee time + start hole */}
      <div className="grid gap-5 sm:grid-cols-3">
        <div className="flex flex-col gap-2">
          <Label htmlFor="round-date" className="text-base font-semibold">
            Dato
          </Label>
          <Input
            id="round-date"
            type="date"
            value={date}
            onChange={(e) => setDate(e.target.value)}
            className="h-14 rounded-2xl text-lg"
          />
        </div>
        <div className="flex flex-col gap-2">
          <Label htmlFor="tee-time" className="text-base font-semibold">
            Utslagstid <span className="font-normal text-muted-foreground">(valgfritt)</span>
          </Label>
          <Input
            id="tee-time"
            type="time"
            value={teeTime}
            onChange={(e) => setTeeTime(e.target.value)}
            className="h-14 rounded-2xl text-lg"
          />
        </div>
        <div className="flex flex-col gap-2">
          <Label htmlFor="start-hole" className="text-base font-semibold">
            Starthull
          </Label>
          <select
            id="start-hole"
            value={startHole}
            onChange={(e) => setStartHole(e.target.value)}
            className="h-14 rounded-2xl border border-input bg-background px-4 text-lg font-semibold text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
          >
            {Array.from({ length: 18 }, (_, i) => i + 1).map((h) => (
              <option key={h} value={String(h)}>
                Hull {h}
              </option>
            ))}
          </select>
        </div>
      </div>

      {/* Statistikknivå -- kun slag er strengt tatt nødvendig for resultat/HCP */}
      <fieldset className="flex flex-col gap-3">
        <legend className="mb-1 text-base font-semibold text-foreground">Statistikk for deg selv</legend>
        <div className="flex flex-col gap-2">
          {(
            [
              { value: "strokes_only", label: "Kun slag", desc: "Raskest -- bare det som trengs for resultat og HCP." },
              { value: "strokes_and_putts", label: "Slag og putter", desc: "Legger til putt-telling per hull." },
              { value: "full", label: "All statistikk", desc: "Kølle, retning, chip, bunker, straffeslag med mer." },
            ] as const
          ).map((opt) => (
            <button
              key={opt.value}
              type="button"
              onClick={() => setStatLevel(opt.value)}
              aria-pressed={statLevel === opt.value}
              className={cn(
                "flex min-h-[44px] flex-col items-start gap-0.5 rounded-2xl border px-5 py-3 text-left transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
                statLevel === opt.value
                  ? "border-primary bg-primary/10"
                  : "border-border bg-card hover:bg-accent/50",
              )}
            >
              <span className="text-base font-bold text-foreground">{opt.label}</span>
              <span className="text-sm text-muted-foreground">{opt.desc}</span>
            </button>
          ))}
        </div>
      </fieldset>

      {/* Spilleform (ADR-038/ADR-039) -- selvdeklarert, ingen egen match-/
          skins-motor. match/fourball/foursome/greensome/scramble krever
          sider -- opprettes i selve runden etter at deltakerne er lagt til. */}
      <fieldset className="flex flex-col gap-3">
        <legend className="mb-1 text-base font-semibold text-foreground">Spilleform</legend>
        <div className="grid grid-cols-2 gap-3 sm:grid-cols-4">
          {PLAY_FORMAT_OPTIONS.map((opt) => (
            <button
              key={opt.value}
              type="button"
              onClick={() => choosePlayFormat(opt.value)}
              aria-pressed={playFormat === opt.value}
              className={cn(
                "flex min-h-[44px] flex-col items-center justify-center gap-0.5 rounded-2xl border px-3 py-3 text-center transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
                playFormat === opt.value
                  ? "border-primary bg-primary/10 text-foreground"
                  : "border-border bg-card text-muted-foreground hover:bg-accent/50 hover:text-foreground",
              )}
            >
              <span className="text-base font-bold">{opt.label}</span>
            </button>
          ))}
        </div>
        <p className="text-sm text-muted-foreground">
          {PLAY_FORMAT_OPTIONS.find((o) => o.value === playFormat)?.desc}
        </p>

        {playFormat === "match" && (
          <label className="flex min-h-[44px] items-start gap-3 rounded-2xl border border-border bg-card px-5 py-3">
            <input
              type="checkbox"
              checked={excludeFromHandicap}
              onChange={(e) => setExcludeFromHandicap(e.target.checked)}
              className="mt-1 size-5 shrink-0 accent-primary"
            />
            <span className="flex flex-col gap-0.5">
              <span className="text-base font-bold text-foreground">
                Ekskluder denne runden fra mitt faktiske HCP
              </span>
              <span className="text-sm text-muted-foreground">
                Anbefalt for match -- konsederte hull gir ofte et upålitelig grunnlag for
                HCP-beregning. Du kan endre dette senere.
              </span>
            </span>
          </label>
        )}

        {playFormat === "skins" && (
          <div className="flex flex-col gap-4 rounded-2xl border border-border bg-card px-5 py-4">
            <div className="flex flex-col gap-2">
              <span className="text-sm font-semibold text-foreground">Poengberegning</span>
              <div className="grid grid-cols-2 gap-2">
                {(
                  [
                    { value: "net" as const, label: "Netto (m/HCP)" },
                    { value: "gross" as const, label: "Brutto" },
                  ]
                ).map((opt) => (
                  <button
                    key={opt.value}
                    type="button"
                    onClick={() => setSkinsScoring(opt.value)}
                    aria-pressed={skinsScoring === opt.value}
                    className={cn(
                      "flex min-h-11 items-center justify-center rounded-xl border text-sm font-bold transition-colors",
                      skinsScoring === opt.value
                        ? "border-primary bg-primary text-primary-foreground"
                        : "border-border bg-background text-foreground hover:bg-accent/50",
                    )}
                  >
                    {opt.label}
                  </button>
                ))}
              </div>
            </div>
            <div className="flex flex-col gap-2">
              <span className="text-sm font-semibold text-foreground">Ved uavgjort hull</span>
              <div className="grid grid-cols-2 gap-2">
                {(
                  [
                    { value: "carry" as const, label: "Rullerer over" },
                    { value: "split" as const, label: "Deles likt" },
                  ]
                ).map((opt) => (
                  <button
                    key={opt.value}
                    type="button"
                    onClick={() => setSkinsTieHandling(opt.value)}
                    aria-pressed={skinsTieHandling === opt.value}
                    className={cn(
                      "flex min-h-11 items-center justify-center rounded-xl border text-sm font-bold transition-colors",
                      skinsTieHandling === opt.value
                        ? "border-primary bg-primary text-primary-foreground"
                        : "border-border bg-background text-foreground hover:bg-accent/50",
                    )}
                  >
                    {opt.label}
                  </button>
                ))}
              </div>
            </div>
            <p className="text-sm text-muted-foreground">
              Skins krever minst 3 spillere i runden -- legg til medspillere etter at runden er opprettet.
            </p>
          </div>
        )}

        {needsSidesSetup && (
          <p className="text-sm text-muted-foreground">
            Du setter opp sidene (og fordeler spillerne) inne i runden, etter at medspillerne er
            lagt til.
          </p>
        )}
      </fieldset>

      {/* Hole count */}
      <fieldset className="flex flex-col gap-3">
        <legend className="mb-1 text-base font-semibold text-foreground">Antall hull</legend>
        <div className="grid grid-cols-2 gap-3">
          {([9, 18] as const).map((count) => (
            <button
              key={count}
              type="button"
              onClick={() => setHoles(count)}
              aria-pressed={holes === count}
              className={cn(
                "flex min-h-[44px] items-center justify-center rounded-2xl border px-4 py-5 text-xl font-extrabold transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
                holes === count
                  ? "border-primary bg-primary/10 text-foreground"
                  : "border-border bg-card text-muted-foreground hover:bg-accent/50 hover:text-foreground",
              )}
            >
              {count} hull
            </button>
          ))}
        </div>
      </fieldset>

      {/* Synlighet (ADR-036 Beslutning B, fase 2) -- styrer KUN tredjeparts
          innsyn (venner/offentligheten), aldri en faktisk lagt-til
          medspiller (som alltid ser runden uansett). Trygg standard
          "Privat", samme filosofi som RLS-policyenes "se ingenting" ved
          manglende kontekst ellers i appen. */}
      <fieldset className="flex flex-col gap-3">
        <legend className="mb-1 text-base font-semibold text-foreground">Synlighet</legend>
        <div className="grid grid-cols-3 gap-2">
          {(
            [
              { value: "private", label: "Privat", desc: "Kun deg og faktiske medspillere." },
              { value: "friends", label: "Venner", desc: "Valgte venne-kategorier kan følge live." },
              { value: "public", label: "Offentlig", desc: "Alle kan følge live, ingen innlogging." },
            ] as { value: VisibilityMode; label: string; desc: string }[]
          ).map((opt) => (
            <button
              key={opt.value}
              type="button"
              onClick={() => setVisibilityMode(opt.value)}
              aria-pressed={visibilityMode === opt.value}
              className={cn(
                "flex min-h-[44px] flex-col items-center gap-0.5 rounded-2xl border px-2 py-3 text-center transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
                visibilityMode === opt.value
                  ? "border-primary bg-primary/10 text-foreground"
                  : "border-border bg-card text-muted-foreground hover:bg-accent/50 hover:text-foreground",
              )}
            >
              <span className="text-sm font-bold">{opt.label}</span>
              <span className="text-xs">{opt.desc}</span>
            </button>
          ))}
        </div>
        {visibilityMode === "friends" && (
          <div className="flex flex-col gap-2 rounded-2xl border border-border bg-card p-4">
            <p className="text-sm font-semibold text-foreground">
              Hvilke av dine venne-kategorier skal kunne se runden? Alle er forhåndsvalgt — velg heller bort det
              du ikke vil skal se den.
            </p>
            <div className="flex flex-wrap gap-2">
              {VISIBILITY_CATEGORY_OPTIONS.map(({ code, label }) => {
                const active = visibleCategories.includes(code)
                return (
                  <button
                    key={code}
                    type="button"
                    onClick={() =>
                      setVisibleCategories((prev) =>
                        active ? prev.filter((c) => c !== code) : [...prev, code],
                      )
                    }
                    aria-pressed={active}
                    className={cn(
                      "min-h-[44px] rounded-full border px-3 text-sm font-semibold transition-colors",
                      active
                        ? "border-primary bg-primary text-primary-foreground"
                        : "border-border bg-background text-muted-foreground hover:bg-accent/50",
                    )}
                  >
                    {label}
                  </button>
                )
              })}
            </div>
            {visibleCategories.length === 0 && (
              <p className="text-xs text-muted-foreground">
                Ingen kategori valgt ennå -- ingen venner kan se runden før du velger minst én.
              </p>
            )}
          </div>
        )}
      </fieldset>

      <Button
        type="button"
        size="lg"
        disabled={submitting || compatibleTees.length === 0 || !selectedTee}
        onClick={handleStart}
        className="h-16 rounded-2xl text-xl font-extrabold shadow-sm"
      >
        {submitting ? "Oppretter…" : "Start runden"}
      </Button>
    </div>
  )
}
