"use client"

import type React from "react"
import { useEffect, useMemo, useState } from "react"
import Link from "next/link"
import {
  ArrowLeft,
  Check,
  ChevronLeft,
  ChevronRight,
  ChevronsUpDown,
  Minus,
  Plus,
  Trophy,
} from "lucide-react"
import { Button } from "@/components/ui/button"
import { cn } from "@/lib/utils"

// --- Types (matcher API-kontrakten i app/routers/tournaments.py/matches.py/scoring.py/courses.py)

type Format = "foursome" | "greensome" | "scramble_2" | "scramble_4" | "fourball" | "singles"
type ScoringMode = "stroke" | "hole_result"
type HoleConfig = "full_18" | "front_9" | "back_9"

const INDIVIDUAL_FORMATS: Format[] = ["singles", "fourball"]

const FORMAT_LABELS: Record<Format, string> = {
  foursome: "Foursome",
  greensome: "Greensome",
  scramble_2: "Scramble (2)",
  scramble_4: "Scramble (4)",
  fourball: "Fourball",
  singles: "Singel",
}

type ApiTeam = { id: string; name: string; color: string | null }

type ApiSession = {
  id: string
  name: string | null
  format: Format
  hole_config: HoleConfig
  course_id: string
  scoring_mode: ScoringMode
}

type ApiParticipant = {
  id: string
  team_side: "a" | "b"
  team_roster_id: string
  player_name: string
  tee_id: string
  tee_name: string
}

type ApiMatch = {
  id: string
  sequence: number
  team_a_id: string
  team_b_id: string
  participants: ApiParticipant[]
}

type ApiHole = { hole_number: number; par: number; stroke_index: number }

type ApiHoleScore = {
  hole_number: number
  team_side: "a" | "b"
  match_participant_id: string | null
  gross_strokes: number
}

type ApiHoleResult = { hole_number: number; winning_side: "a" | "b" | null }

type ApiScorecard = {
  match_id: string
  status_text: string | null
  points_side_a: number | null
  points_side_b: number | null
  holes: { hole_number: number; result: "a" | "b" | "halved" }[]
  stroke_entries: ApiHoleScore[] | null
  hole_result_entries: ApiHoleResult[] | null
}

// Enhet som scores: én per SPILLER for individuelle formater (singles/
// fourball), én per SIDE for delt-ball-formater (foursome/greensome/
// scramble) -- se app/routers/scoring.py sin is_individual-sjekk.
type Unit = { id: string; side: "a" | "b"; label: string; matchParticipantId: string | null }

function playedHoleNumbers(holeConfig: HoleConfig): number[] {
  if (holeConfig === "front_9") return Array.from({ length: 9 }, (_, i) => i + 1)
  if (holeConfig === "back_9") return Array.from({ length: 9 }, (_, i) => i + 10)
  return Array.from({ length: 18 }, (_, i) => i + 1)
}

export function SessionScorecard({
  organizationId,
  tournamentId,
  sessionId,
  matchId,
  tournamentName,
}: {
  organizationId: string
  tournamentId: string
  sessionId: string
  matchId: string
  tournamentName: string
}) {
  const [session, setSession] = useState<ApiSession | null>(null)
  const [teams, setTeams] = useState<[ApiTeam, ApiTeam] | null>(null)
  const [match, setMatch] = useState<ApiMatch | null>(null)
  const [holes, setHoles] = useState<ApiHole[]>([])
  const [scorecard, setScorecard] = useState<ApiScorecard | null>(null)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [currentHole, setCurrentHole] = useState<number | null>(null)
  const [showSummary, setShowSummary] = useState(false)

  async function refetchScorecard() {
    const res = await fetch(`/orgs/${organizationId}/matches/${matchId}/scorecard`, {
      credentials: "include",
    })
    if (res.ok) setScorecard(await res.json())
  }

  useEffect(() => {
    let cancelled = false
    async function load() {
      try {
        const [sessionsRes, teamsRes, matchesRes] = await Promise.all([
          fetch(`/orgs/${organizationId}/tournaments/${tournamentId}/sessions`, { credentials: "include" }),
          fetch(`/orgs/${organizationId}/tournaments/${tournamentId}/teams`, { credentials: "include" }),
          fetch(`/orgs/${organizationId}/sessions/${sessionId}/matches`, { credentials: "include" }),
        ])
        if (!sessionsRes.ok || !teamsRes.ok || !matchesRes.ok) throw new Error("load failed")
        const sessionsData: ApiSession[] = await sessionsRes.json()
        const foundSession = sessionsData.find((s) => s.id === sessionId)
        if (!foundSession) throw new Error("session not found")
        const teamsData: ApiTeam[] = await teamsRes.json()
        if (teamsData.length !== 2) throw new Error("expected 2 teams")
        const matchesData: ApiMatch[] = await matchesRes.json()
        const foundMatch = matchesData.find((m) => m.id === matchId)
        if (!foundMatch) throw new Error("match not found")

        const [holesRes, scorecardRes] = await Promise.all([
          fetch(`/orgs/${organizationId}/courses/${foundSession.course_id}/holes`, { credentials: "include" }),
          fetch(`/orgs/${organizationId}/matches/${matchId}/scorecard`, { credentials: "include" }),
        ])
        if (!holesRes.ok || !scorecardRes.ok) throw new Error("load failed")
        const holesData: ApiHole[] = await holesRes.json()
        const scorecardData: ApiScorecard = await scorecardRes.json()

        if (cancelled) return
        setSession(foundSession)
        setTeams([teamsData[0], teamsData[1]])
        setMatch(foundMatch)
        setHoles(holesData)
        setScorecard(scorecardData)
        const played = playedHoleNumbers(foundSession.hole_config)
        const nextUnregistered = played[scorecardData.holes.length] ?? played[played.length - 1]
        setCurrentHole(nextUnregistered)
      } catch {
        if (!cancelled) setError("Klarte ikke å laste scorekortet. Prøv å laste siden på nytt.")
      } finally {
        if (!cancelled) setLoading(false)
      }
    }
    void load()
    return () => {
      cancelled = true
    }
  }, [organizationId, tournamentId, sessionId, matchId])

  const units: Unit[] = useMemo(() => {
    if (!session || !match || !teams) return []
    const isIndividual = INDIVIDUAL_FORMATS.includes(session.format)
    if (isIndividual) {
      return match.participants.map((p) => ({
        id: p.id,
        side: p.team_side,
        label: p.player_name,
        matchParticipantId: p.id,
      }))
    }
    return [
      { id: "a", side: "a", label: teams[0].name, matchParticipantId: null },
      { id: "b", side: "b", label: teams[1].name, matchParticipantId: null },
    ]
  }, [session, match, teams])

  const decided = scorecard?.points_side_a !== null && scorecard?.points_side_b !== null

  async function submitStroke(holeNumber: number, unit: Unit, grossStrokes: number) {
    setError(null)
    try {
      const res = await fetch(`/orgs/${organizationId}/matches/${matchId}/hole-scores`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        credentials: "include",
        body: JSON.stringify({
          team_side: unit.side,
          match_participant_id: unit.matchParticipantId,
          hole_number: holeNumber,
          gross_strokes: grossStrokes,
        }),
      })
      if (!res.ok) throw new Error(`submit stroke: ${res.status}`)
      await refetchScorecard()
    } catch {
      setError("Klarte ikke å registrere slaget. Kanskje matchen allerede er avgjort.")
    }
  }

  async function submitHoleResult(holeNumber: number, winningSide: "a" | "b" | null) {
    setError(null)
    try {
      const res = await fetch(`/orgs/${organizationId}/matches/${matchId}/hole-results`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        credentials: "include",
        body: JSON.stringify({ hole_number: holeNumber, winning_side: winningSide }),
      })
      if (!res.ok) throw new Error(`submit result: ${res.status}`)
      await refetchScorecard()
    } catch {
      setError("Klarte ikke å registrere hull-resultatet. Kanskje matchen allerede er avgjort.")
    }
  }

  const programHref = `/tournaments/${tournamentId}/program?org=${organizationId}&name=${encodeURIComponent(tournamentName)}`

  if (loading || !session || !teams || !match || !scorecard || currentHole === null) {
    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 gap-3 px-5 py-4">
            <Link
              href={programHref}
              aria-label="Tilbake til program"
              className="flex size-10 shrink-0 items-center justify-center rounded-xl border border-border bg-card text-muted-foreground transition-colors hover:bg-accent/50 hover:text-foreground"
            >
              <ArrowLeft aria-hidden="true" className="size-5" />
            </Link>
            <div className="flex min-w-0 flex-col">
              <span className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
                Turnering
              </span>
              <h1 className="truncate text-xl font-extrabold tracking-tight text-foreground">
                {tournamentName}
              </h1>
            </div>
          </div>
        </header>
        <main className="mx-auto flex w-full max-w-3xl flex-1 items-center justify-center px-5 py-6">
          {error ? (
            <p role="alert" className="text-sm font-medium text-destructive">
              {error}
            </p>
          ) : (
            <div
              aria-hidden="true"
              className="size-10 animate-spin rounded-full border-4 border-primary/20 border-t-primary"
            />
          )}
        </main>
      </div>
    )
  }

  const played = playedHoleNumbers(session.hole_config)
  const totalHoles = played.length
  const par = holes.find((h) => h.hole_number === currentHole)?.par ?? 4
  const registeredHoleNumbers = new Set(scorecard.holes.map((h) => h.hole_number))

  const statusLabel = scorecard.status_text ?? "AS"

  function strokeValue(holeNumber: number, unit: Unit): number | null {
    const entry = (scorecard!.stroke_entries ?? []).find(
      (e) =>
        e.hole_number === holeNumber &&
        e.team_side === unit.side &&
        e.match_participant_id === unit.matchParticipantId,
    )
    return entry ? entry.gross_strokes : null
  }

  function stepStroke(unit: Unit, delta: number) {
    const current = strokeValue(currentHole!, unit)
    const base = current === null ? par : current
    const next = Math.max(1, Math.min(20, base + delta))
    void submitStroke(currentHole!, unit, next)
  }

  const currentResultEntry = (scorecard.hole_result_entries ?? []).find(
    (e) => e.hole_number === currentHole,
  )

  function goPrev() {
    setCurrentHole((h) => {
      const idx = played.indexOf(h!)
      return played[Math.max(0, idx - 1)]
    })
  }
  function goNext() {
    setCurrentHole((h) => {
      const idx = played.indexOf(h!)
      return played[Math.min(played.length - 1, idx + 1)]
    })
  }

  const isIndividual = INDIVIDUAL_FORMATS.includes(session.format)
  const isLast = played.indexOf(currentHole) >= played.length - 1

  return (
    <div className="flex min-h-[100dvh] flex-col bg-background">
      <header className="sticky top-0 z-20 border-b border-border bg-background/80 backdrop-blur">
        <div className="mx-auto flex w-full max-w-3xl items-center gap-3 px-5 py-4">
          <Link
            href={programHref}
            aria-label="Tilbake til program"
            className="flex size-10 shrink-0 items-center justify-center rounded-xl border border-border bg-card text-muted-foreground transition-colors hover:bg-accent/50 hover:text-foreground"
          >
            <ArrowLeft aria-hidden="true" className="size-5" />
          </Link>
          <div className="flex min-w-0 flex-col">
            <span className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
              Turnering
            </span>
            <h1 className="truncate text-xl font-extrabold tracking-tight text-foreground">
              {tournamentName}
            </h1>
            <span className="truncate text-sm text-muted-foreground">
              {session.name?.trim() || "Økt"} · {FORMAT_LABELS[session.format]} · Match {match.sequence}
            </span>
          </div>
        </div>

        <div className="border-t border-border bg-card/40">
          <div className="mx-auto grid w-full max-w-3xl grid-cols-[1fr_auto_1fr] items-center gap-2 px-5 py-3 sm:gap-4">
            <TeamTag name={teams[0].name} color={teams[0].color ?? "#64748b"} align="left" />
            {decided ? (
              <div className="flex flex-col items-center px-1">
                <span className="text-lg font-extrabold tracking-tight text-primary">Avgjort</span>
              </div>
            ) : (
              <div className="flex items-center gap-1.5 sm:gap-3">
                <button
                  type="button"
                  onClick={goPrev}
                  disabled={played.indexOf(currentHole) <= 0}
                  aria-label="Forrige hull"
                  className="flex size-11 shrink-0 items-center justify-center rounded-2xl border border-border bg-card text-foreground transition-colors hover:bg-accent/50 disabled:opacity-40"
                >
                  <ChevronLeft aria-hidden="true" className="size-5" />
                </button>
                <div className="flex min-w-[84px] flex-col items-center">
                  <span className="text-2xl font-extrabold leading-none tracking-tight text-foreground tabular-nums">
                    {statusLabel}
                  </span>
                </div>
                <button
                  type="button"
                  onClick={goNext}
                  disabled={isLast}
                  aria-label="Neste hull"
                  className="flex size-11 shrink-0 items-center justify-center rounded-2xl border border-border bg-card text-foreground transition-colors hover:bg-accent/50 disabled:opacity-40"
                >
                  <ChevronRight aria-hidden="true" className="size-5" />
                </button>
              </div>
            )}
            <TeamTag name={teams[1].name} color={teams[1].color ?? "#64748b"} align="right" />
          </div>
        </div>
      </header>

      <main className="mx-auto w-full max-w-3xl flex-1 px-5 py-6 sm:py-8">
        {error && (
          <p role="alert" className="mb-4 text-sm font-medium text-destructive">
            {error}
          </p>
        )}

        {decided ? (
          <DecidedView
            teams={teams}
            scorecard={scorecard}
            holes={holes}
            units={units}
            scoringMode={session.scoring_mode}
          />
        ) : (
          <>
            <nav aria-label="Velg hull" className="-mx-5 mb-4 overflow-x-auto px-5">
              <div className="flex gap-2 pb-1">
                {played.map((h) => {
                  const active = h === currentHole
                  const registered = registeredHoleNumbers.has(h)
                  return (
                    <button
                      key={h}
                      type="button"
                      onClick={() => setCurrentHole(h)}
                      aria-current={active ? "true" : undefined}
                      className={cn(
                        "relative flex size-11 shrink-0 flex-col items-center justify-center rounded-2xl border text-sm font-bold tabular-nums transition-colors",
                        active
                          ? "border-primary bg-primary text-primary-foreground"
                          : "border-border bg-card text-foreground hover:bg-accent/50",
                      )}
                    >
                      {h}
                      {registered && (
                        <span
                          aria-hidden="true"
                          className={cn(
                            "absolute -right-0.5 -top-0.5 flex size-4 items-center justify-center rounded-full border-2 border-background",
                            active ? "bg-primary-foreground text-primary" : "bg-primary text-primary-foreground",
                          )}
                        >
                          <Check className="size-2.5" strokeWidth={3} />
                        </span>
                      )}
                    </button>
                  )
                })}
              </div>
            </nav>

            <div className="mb-4 overflow-hidden rounded-2xl border border-border bg-card">
              <button
                type="button"
                onClick={() => setShowSummary((v) => !v)}
                aria-expanded={showSummary}
                className="flex w-full items-center justify-between gap-2 px-4 py-3 text-left"
              >
                <span className="text-sm font-semibold text-foreground">Vis full oversikt</span>
                <ChevronsUpDown aria-hidden="true" className="size-4 text-muted-foreground" />
              </button>
              {showSummary && (
                <div className="border-t border-border">
                  <HoleSummaryTable teams={teams} scorecard={scorecard} holes={holes} scoringMode={session.scoring_mode} />
                </div>
              )}
            </div>

            {session.scoring_mode === "stroke" ? (
              <section aria-label={`Hull ${currentHole}`}>
                <div className="mb-4 flex items-baseline gap-2">
                  <h2 className="text-2xl font-extrabold tracking-tight text-foreground">Hull {currentHole}</h2>
                  <span className="text-lg font-bold text-muted-foreground">· Par {par}</span>
                </div>
                <div className="flex flex-col gap-3">
                  {units.map((unit) => {
                    const teamColor = (unit.side === "a" ? teams[0].color : teams[1].color) ?? "#64748b"
                    const value = strokeValue(currentHole, unit)
                    return (
                      <div
                        key={unit.id}
                        className="flex flex-col gap-3 rounded-3xl border border-border bg-card p-4 shadow-sm shadow-black/5 sm:p-5"
                        style={{ borderLeftWidth: 6, borderLeftColor: teamColor }}
                      >
                        <div className="flex items-center gap-2.5">
                          <span aria-hidden="true" className="size-3.5 shrink-0 rounded-full" style={{ backgroundColor: teamColor }} />
                          <span className="text-base font-bold tracking-tight text-foreground text-pretty">
                            {unit.label}
                          </span>
                          {!isIndividual && (
                            <span className="text-xs font-medium text-muted-foreground">(delt ball)</span>
                          )}
                        </div>
                        <div className="flex items-center justify-between gap-3">
                          <button
                            type="button"
                            onClick={() => stepStroke(unit, -1)}
                            aria-label={`Ett slag mindre for ${unit.label}`}
                            className="flex size-14 shrink-0 items-center justify-center rounded-2xl border border-border bg-secondary text-secondary-foreground transition-colors hover:bg-accent active:scale-95"
                          >
                            <Minus aria-hidden="true" className="size-6" />
                          </button>
                          <div className="flex flex-1 flex-col items-center">
                            <span
                              className={cn(
                                "text-5xl font-extrabold leading-none tabular-nums",
                                value === null ? "text-muted-foreground/40" : "text-foreground",
                              )}
                            >
                              {value === null ? "–" : value}
                            </span>
                            <span className="mt-1 text-xs font-medium text-muted-foreground">
                              {value === null ? "Ikke registrert" : scoreToParLabel(value, par)}
                            </span>
                          </div>
                          <button
                            type="button"
                            onClick={() => stepStroke(unit, 1)}
                            aria-label={`Ett slag mer for ${unit.label}`}
                            className="flex size-14 shrink-0 items-center justify-center rounded-2xl bg-primary text-primary-foreground transition-colors hover:bg-primary/90 active:scale-95"
                          >
                            <Plus aria-hidden="true" className="size-6" />
                          </button>
                        </div>
                      </div>
                    )
                  })}
                </div>
              </section>
            ) : (
              <section aria-label={`Hull ${currentHole}`}>
                <div className="mb-4 flex items-baseline gap-2">
                  <h2 className="text-2xl font-extrabold tracking-tight text-foreground">Hull {currentHole}</h2>
                  <span className="text-lg font-bold text-muted-foreground">· Par {par}</span>
                </div>
                <div className="grid grid-cols-1 gap-3 sm:grid-cols-3">
                  {(
                    [
                      { key: "a", label: `${teams[0].name} vant`, color: teams[0].color, side: "a" as const },
                      { key: "h", label: "Delt", color: undefined, side: null },
                      { key: "b", label: `${teams[1].name} vant`, color: teams[1].color, side: "b" as const },
                    ] as const
                  ).map((opt) => {
                    const active = currentResultEntry
                      ? currentResultEntry.winning_side === opt.side
                      : false
                    return (
                      <button
                        key={opt.key}
                        type="button"
                        onClick={() => submitHoleResult(currentHole, opt.side)}
                        aria-pressed={active}
                        className={cn(
                          "flex h-16 items-center justify-center gap-2 rounded-2xl border text-base font-bold tracking-tight transition-colors",
                          active
                            ? opt.color
                              ? "border-transparent text-primary-foreground"
                              : "border-primary bg-primary text-primary-foreground"
                            : "border-border bg-card text-foreground hover:bg-accent/50",
                        )}
                        style={active && opt.color ? { backgroundColor: opt.color } : undefined}
                      >
                        {opt.color && (
                          <span
                            aria-hidden="true"
                            className="size-3.5 rounded-full"
                            style={{ backgroundColor: active ? undefined : opt.color }}
                          />
                        )}
                        {opt.label}
                      </button>
                    )
                  })}
                </div>
              </section>
            )}

            <div className="mt-6">
              {!isLast ? (
                <Button type="button" onClick={goNext} className="h-14 w-full rounded-2xl text-base font-bold shadow-sm">
                  Neste hull
                  <ChevronRight aria-hidden="true" className="size-5" />
                </Button>
              ) : (
                <Button
                  type="button"
                  onClick={() => setShowSummary(true)}
                  className="h-14 w-full rounded-2xl text-base font-bold shadow-sm"
                >
                  <Check aria-hidden="true" className="size-5" />
                  Ferdig
                </Button>
              )}
            </div>
          </>
        )}
      </main>
    </div>
  )
}

// --- Small components --------------------------------------------------------

function TeamTag({ name, color, align }: { name: string; color: string; align: "left" | "right" }) {
  const right = align === "right"
  return (
    <div className={cn("flex min-w-0 items-center gap-2", right ? "flex-row-reverse text-right" : "text-left")}>
      <span aria-hidden="true" className="size-3.5 shrink-0 rounded-full" style={{ backgroundColor: color }} />
      <span className="truncate text-sm font-bold tracking-tight text-foreground">{name}</span>
    </div>
  )
}

function HoleSummaryTable({
  teams,
  scorecard,
  holes,
  scoringMode,
}: {
  teams: [ApiTeam, ApiTeam]
  scorecard: ApiScorecard
  holes: ApiHole[]
  scoringMode: ScoringMode
}) {
  if (scorecard.holes.length === 0) {
    return <p className="px-4 py-4 text-sm text-muted-foreground">Ingen hull er registrert ennå.</p>
  }

  return (
    <ul className="divide-y divide-border">
      {scorecard.holes.map((h) => {
        const par = holes.find((x) => x.hole_number === h.hole_number)?.par
        return (
          <li key={h.hole_number} className="flex items-center justify-between gap-3 px-4 py-2.5">
            <div className="flex items-center gap-2.5">
              <span className="flex size-8 items-center justify-center rounded-xl bg-secondary text-sm font-extrabold tabular-nums text-secondary-foreground">
                {h.hole_number}
              </span>
              {par !== undefined && (
                <span className="text-xs font-medium text-muted-foreground">Par {par}</span>
              )}
              {scoringMode === "stroke" && (
                <span className="text-xs tabular-nums text-muted-foreground">
                  {grossPairLabel(scorecard, h.hole_number)}
                </span>
              )}
            </div>
            <OutcomeBadge teams={teams} result={h.result} />
          </li>
        )
      })}
    </ul>
  )
}

function grossPairLabel(scorecard: ApiScorecard, holeNumber: number): string {
  const entries = scorecard.stroke_entries ?? []
  const sideGross = (side: "a" | "b"): string => {
    const vals = entries.filter((e) => e.hole_number === holeNumber && e.team_side === side).map((e) => e.gross_strokes)
    if (vals.length === 0) return "–"
    return String(Math.min(...vals))
  }
  return `${sideGross("a")}–${sideGross("b")}`
}

function OutcomeBadge({ teams, result }: { teams: [ApiTeam, ApiTeam]; result: "a" | "b" | "halved" }) {
  if (result === "halved") {
    return (
      <span className="inline-flex items-center rounded-full bg-secondary px-2.5 py-1 text-xs font-semibold text-secondary-foreground">
        Delt
      </span>
    )
  }
  const team = result === "a" ? teams[0] : teams[1]
  return (
    <span
      className="inline-flex items-center gap-1.5 rounded-full px-2.5 py-1 text-xs font-semibold text-primary-foreground"
      style={{ backgroundColor: team.color ?? "#64748b" }}
    >
      {team.name}
    </span>
  )
}

function scoreToParLabel(value: number, par: number): string {
  const diff = value - par
  if (diff === 0) return "Par"
  if (diff === -1) return "Birdie"
  if (diff === -2) return "Eagle"
  if (diff <= -3) return "Albatross"
  if (diff === 1) return "Bogey"
  if (diff === 2) return "Dobbel bogey"
  return `+${diff}`
}

function DecidedView({
  teams,
  scorecard,
  holes,
  units,
  scoringMode,
}: {
  teams: [ApiTeam, ApiTeam]
  scorecard: ApiScorecard
  holes: ApiHole[]
  units: Unit[]
  scoringMode: ScoringMode
}) {
  return (
    <div className="flex flex-col gap-6">
      <div className="flex items-center gap-4 rounded-3xl bg-primary px-5 py-5 text-primary-foreground shadow-sm">
        <div className="flex size-14 shrink-0 items-center justify-center rounded-2xl bg-primary-foreground/15">
          <Trophy aria-hidden="true" className="size-7" />
        </div>
        <div className="flex flex-col">
          <span className="text-lg font-extrabold tracking-tight">Matchen er avgjort</span>
          <span className="text-sm text-primary-foreground/85 text-pretty">{scorecard.status_text ?? ""}</span>
        </div>
      </div>

      <div className="grid grid-cols-3 items-center gap-2 rounded-3xl border border-border bg-card px-5 py-4 shadow-sm">
        <div className="flex flex-col items-start gap-1">
          <div className="flex items-center gap-2">
            <span aria-hidden="true" className="size-3.5 rounded-full" style={{ backgroundColor: teams[0].color ?? "#64748b" }} />
            <span className="text-sm font-bold text-foreground text-pretty">{teams[0].name}</span>
          </div>
          <span className="text-3xl font-extrabold tabular-nums text-foreground">
            {formatPoints(scorecard.points_side_a ?? 0)}
          </span>
        </div>
        <div className="text-center text-xs font-semibold uppercase tracking-wide text-muted-foreground">Poeng</div>
        <div className="flex flex-col items-end gap-1">
          <div className="flex flex-row-reverse items-center gap-2">
            <span aria-hidden="true" className="size-3.5 rounded-full" style={{ backgroundColor: teams[1].color ?? "#64748b" }} />
            <span className="text-sm font-bold text-foreground text-pretty">{teams[1].name}</span>
          </div>
          <span className="text-3xl font-extrabold tabular-nums text-foreground">
            {formatPoints(scorecard.points_side_b ?? 0)}
          </span>
        </div>
      </div>

      <div>
        <h2 className="mb-3 text-sm font-semibold uppercase tracking-wide text-muted-foreground">Hull for hull</h2>
        <div className="overflow-hidden rounded-2xl border border-border bg-card">
          <HoleSummaryTable teams={teams} scorecard={scorecard} holes={holes} scoringMode={scoringMode} />
        </div>
        <p className="mt-3 text-center text-xs text-muted-foreground text-pretty">
          Resultatet kan ikke endres etter at matchen er avgjort.
        </p>
      </div>
    </div>
  )
}

function formatPoints(points: number) {
  return Number.isInteger(points) ? String(points) : points.toFixed(1).replace(".", ",")
}
