"use client"

// Aggregert statistikk på tvers av "Egne runder" (ADR-033), lenket fra
// dashbordets "Statistikk"-seksjon. Egen backend-aggregering
// (GET /rounds/stats/summary) -- ikke bare klientside-utledning av
// round-stats.tsx sin logikk, siden putt/18-hull-regelen (padding av
// uspilte hull til 2 putter, KUN for dette tallet) og "forrige periode"-
// vinduet må regnes over ALLE fullførte runder samlet, ikke én om gangen.
//
// Visuell versjon 2 (2026-07-28): brukeren delte et referansebilde av en
// konkurrent-app sin statistikkskjerm (donuter med sentertall, kompass-
// diagram for miss-retning) og ba om noe tilsvarende -- håndkodet direkte
// (ingen V0-credits igjen), verifisert med ekte skjermbilder via Chrome
// DevTools MCP i stedet for kun typesjekk, se CLAUDE.md. Inspirert av
// referansen, ikke kopiert: egne farger/ikonografi, ingen flyt-diagram for
// scrambling/sand save (ville antydet en forgrening dataene ikke har -- det
// er to uavhengige prosenter, ikke en beslutningstre), ingen trendlinje
// ennå (for lite rundehistorikk til å være meningsfullt, se CLAUDE.md).

import type React from "react"
import { useEffect, useState } from "react"
import { useRouter } from "next/navigation"
import Link from "next/link"
import { ArrowDown, ArrowLeft, ArrowRight, ArrowUp, BarChart3, Flag, TrendingDown, TrendingUp, Waves, Wind } from "lucide-react"

type ApiRoundSeriesPoint = {
  played_at: string
  score_to_par: number
  putts_per_18: number | null
  fairway_hit_pct: number | null
  gir_pct: number | null
  one_putt_pct: number | null
  chip_per_round: number | null
  bunker_per_round: number | null
  penalty_per_round: number | null
  anyway_per_round: number | null
  scrambling_cumulative_pct: number | null
  sand_save_cumulative_pct: number | null
}

type ApiStatsSummary = {
  rounds_completed: number
  avg_score_to_par: number | null
  avg_putts_per_18: number | null
  putts_tracked_rounds: number
  fairway_hit_pct: number | null
  fairway_left_pct: number | null
  fairway_right_pct: number | null
  fairway_tracked_holes: number
  gir_pct: number | null
  gir_tracked_holes: number
  green_miss_long_pct: number | null
  green_miss_short_pct: number | null
  green_miss_left_pct: number | null
  green_miss_right_pct: number | null
  green_miss_tracked_holes: number
  one_putt_pct: number | null
  putt_dist_one_pct: number | null
  putt_dist_two_pct: number | null
  putt_dist_three_plus_pct: number | null
  scrambling_pct: number | null
  sand_save_pct: number | null
  avg_chip_per_round: number | null
  avg_bunker_per_round: number | null
  avg_penalty_per_round: number | null
  avg_anyway_per_round: number | null
  avg_to_par_with_gir: number | null
  avg_to_par_without_gir: number | null
  avg_to_par_fairway_hit: number | null
  avg_to_par_fairway_miss: number | null
  avg_to_par_with_bunker: number | null
  avg_to_par_without_bunker: number | null
  avg_to_par_with_anyway: number | null
  avg_to_par_without_anyway: number | null
}

type ApiWindowSummary = {
  window: string
  current: ApiStatsSummary
  previous: ApiStatsSummary
  round_series: ApiRoundSeriesPoint[]
}

type WindowKey = "last_round" | "last_5" | "last_10" | "month" | "year" | "last_year" | "all"

const WINDOW_OPTIONS: { key: WindowKey; label: string }[] = [
  { key: "last_round", label: "Siste runde" },
  { key: "last_5", label: "Siste 5" },
  { key: "last_10", label: "Siste 10" },
  { key: "month", label: "Denne måneden" },
  { key: "year", label: "I år" },
  { key: "last_year", label: "Siste år" },
  { key: "all", label: "Alltid" },
]

function signed(n: number): string {
  const sign = n > 0 ? "+" : n < 0 ? "−" : "±"
  return `${sign}${Math.abs(n).toFixed(1).replace(".", ",")}`
}

function pct(n: number): string {
  return `${Math.round(n)} %`
}

// Enhetsløs versjon av `pct` -- til bruk som `formatSlope` i BarTrendChart
// der `slopeSuffix` allerede bærer enheten ("pp per runde"); `pct` sin
// egen "%" ville da kollidert med det.
function roundedNoUnit(n: number): string {
  return String(Math.round(n))
}

function oneDecimal(n: number): string {
  return n.toFixed(1).replace(".", ",")
}

// Prosentpoeng-differanse mellom to andeler (ikke "N % endring", men "N pp").
function signedPoints(n: number): string {
  const rounded = Math.round(n)
  const sign = rounded > 0 ? "+" : rounded < 0 ? "−" : "±"
  return `${sign}${Math.abs(rounded)} pp`
}

// "up" = høyere tall er bedre (fairwaytreff, GIR, ...), "down" = lavere
// tall er bedre (snitt til par, putt/runde, ...). Utelatt = ren beskrivende
// retning (miss-retning venstre/høyre osv.) -- ingen "bedre/verre" der.
function Delta({
  current,
  previous,
  format,
  goodDirection,
}: {
  current: number | null
  previous: number | null
  format: (diff: number) => string
  goodDirection?: "up" | "down"
}) {
  // Teksten "vs. forrige periode" var tidligere KUN skjermleser-tekst --
  // seende brukere så bare et ikon + et tall + "pp", uten noen synlig
  // forklaring på hva tallet ble sammenlignet MOT. Nå alltid synlig, slik
  // at delta-en er selvforklarende alene, uten å måtte lese en fjern
  // overskrift lenger oppe på siden (2026-08-12, brukertilbakemelding).
  if (current === null || previous === null) return null
  const diff = current - previous
  if (diff === 0) {
    return <span className="text-xs font-semibold text-muted-foreground">Uendret vs. forrige periode</span>
  }
  const improved = goodDirection === "up" ? diff > 0 : goodDirection === "down" ? diff < 0 : null
  const Icon = diff > 0 ? TrendingUp : TrendingDown
  const colorClass = improved === true ? "text-primary" : improved === false ? "text-brand-orange" : "text-muted-foreground"
  return (
    <span className={`inline-flex flex-wrap items-center gap-1 text-xs font-bold ${colorClass}`}>
      <Icon aria-hidden="true" className="size-3.5" />
      <span className="tabular-nums">{format(diff)}</span>
      <span className="font-semibold text-muted-foreground">vs. forrige periode</span>
    </span>
  )
}

function StatTile({
  label,
  value,
  hint,
  delta,
}: {
  label: string
  value: string
  hint?: string
  delta?: React.ReactNode
}) {
  return (
    <div className="flex flex-col gap-1 rounded-2xl border border-border bg-card p-4 shadow-md shadow-black/8">
      <span className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">{label}</span>
      <span className="text-2xl font-extrabold tabular-nums text-foreground sm:text-3xl">{value}</span>
      {delta}
      {hint && <span className="text-xs text-muted-foreground">{hint}</span>}
    </div>
  )
}

function Card({ title, subtitle, children }: { title: string; subtitle?: string; children: React.ReactNode }) {
  return (
    <section className="flex flex-col gap-4 rounded-2xl border border-border bg-card p-4 shadow-md shadow-black/8 sm:p-5">
      <div>
        <h2 className="text-lg font-extrabold tracking-tight text-foreground">{title}</h2>
        {subtitle && <p className="text-sm text-muted-foreground">{subtitle}</p>}
      </div>
      {children}
    </section>
  )
}

function Section({
  title,
  icon: Icon,
  children,
}: {
  title: string
  icon: typeof BarChart3
  children: React.ReactNode
}) {
  return (
    <section className="flex flex-col gap-3">
      <h2 className="flex items-center gap-2 text-lg font-extrabold tracking-tight text-foreground">
        <Icon aria-hidden="true" className="size-5 text-primary" />
        {title}
      </h2>
      <div className="grid grid-cols-2 gap-3 sm:grid-cols-3">{children}</div>
    </section>
  )
}

// --- Donut: sentertall + inntil 4 fargede segmenter (conic-gradient) -------
// Gjenbrukt for BÅDE puttfordelingen (3 segmenter) og de enkle rednings-
// gaugene (1 segment fylt + resten "spor"). Prosent er ALLTID skrevet ut i
// en forklaringsliste under -- fargen bærer aldri betydningen alene.

function Donut({
  segments,
  centerValue,
  centerLabel,
  size = 132,
  thickness = 18,
  showLegend = true,
}: {
  segments: { label: string; value: number; color: string }[]
  centerValue: string
  centerLabel: string
  size?: number
  thickness?: number
  showLegend?: boolean
}) {
  let cursor = 0
  const stops: string[] = []
  for (const seg of segments) {
    const start = cursor
    const end = cursor + seg.value
    stops.push(`${seg.color} ${start}% ${end}%`)
    cursor = end
  }
  if (cursor < 100) stops.push(`var(--muted) ${cursor}% 100%`)
  const gradient = `conic-gradient(${stops.join(", ")})`

  const ring = (
    <div
      className="relative shrink-0 rounded-full"
      style={{ width: size, height: size, background: gradient }}
      role="img"
      aria-label={`${centerLabel}: ${centerValue}. ${segments.map((s) => `${s.label} ${Math.round(s.value)} prosent`).join(", ")}`}
    >
      <div
        className="absolute rounded-full bg-card"
        style={{
          width: size - thickness * 2,
          height: size - thickness * 2,
          top: thickness,
          left: thickness,
        }}
      />
      <div className="absolute inset-0 flex flex-col items-center justify-center">
        <span className="text-xl font-extrabold tabular-nums text-foreground">{centerValue}</span>
        <span className="text-[11px] font-semibold text-muted-foreground">{centerLabel}</span>
      </div>
    </div>
  )

  if (!showLegend) return ring

  return (
    <div className="flex flex-col items-center gap-3 sm:flex-row sm:items-center">
      {ring}
      <ul className="flex flex-1 flex-col gap-1.5">
        {segments.map((s) => (
          <li key={s.label} className="flex items-center gap-2 text-sm text-muted-foreground">
            <span aria-hidden="true" className="size-2.5 shrink-0 rounded-full" style={{ backgroundColor: s.color }} />
            <span className="flex-1">{s.label}</span>
            <span className="font-bold tabular-nums text-foreground">{Math.round(s.value)} %</span>
          </li>
        ))}
      </ul>
    </div>
  )
}

// --- Kompass-diagram for greentreff-miss-retning ----------------------------
// Greentreff i midten, langt over, kort under, venstre til venstre, høyre
// til høyre -- speiler hvor bommen faktisk gikk relativt til green, i
// stedet for en flat fordelingsbar. Alle fire retningsceller viser tallet
// sitt som tekst uansett -- retning er beskrivende, ikke god/dårlig, så
// ingen av dem fargekodes grønn/oransje (kun sentercellen, som ER et
// treff/bom-tall, får grønn fremheving).

function CompassCell({ icon: Icon, label, value }: { icon: typeof ArrowUp; label: string; value: number | null }) {
  return (
    <div className="flex min-h-16 flex-col items-center justify-center gap-0.5 rounded-2xl border border-border bg-card p-2">
      <Icon aria-hidden="true" className="size-4 text-muted-foreground" />
      <span className="text-lg font-extrabold tabular-nums text-foreground">{value !== null ? `${Math.round(value)} %` : "–"}</span>
      <span className="text-[11px] font-semibold text-muted-foreground">{label}</span>
    </div>
  )
}

// Greentreff (GIR) og Innspill var tidligere ÉN kombinert komponent
// (GirCompass). Splittet i to 2026-08-12 på brukerens eksplisitte
// instruks: GIR er en beregnet andel (traff/bommet), Innspill er en
// retningsbeskrivelse -- to ulike typer informasjon, samme prinsipp som
// round-stats.tsx sin split mellom "Greentreff (GIR)" og "Bom-retning på
// green" (se den filen).

function GirGauge({ hitPct, trackedHoles }: { hitPct: number | null; trackedHoles: number }) {
  if (hitPct === null) {
    return <p className="text-sm text-muted-foreground">Ingen greentreff-data registrert ennå.</p>
  }
  return (
    <div className="flex flex-col items-center gap-2">
      <Donut
        segments={[
          { label: "Traff green", value: hitPct, color: "var(--primary)" },
          { label: "Bommet green", value: 100 - hitPct, color: "var(--brand-orange)" },
        ]}
        centerValue={`${Math.round(hitPct)} %`}
        centerLabel="GIR"
      />
      <p className="text-xs text-muted-foreground">{trackedHoles} hull registrert</p>
    </div>
  )
}

function ApproachDirectionCompass({
  trackedHoles,
  long,
  short,
  left,
  right,
}: {
  trackedHoles: number
  long: number | null
  short: number | null
  left: number | null
  right: number | null
}) {
  if (trackedHoles === 0) {
    return <p className="text-sm text-muted-foreground">Ingen innspill med retning registrert ennå.</p>
  }
  return (
    <div className="flex flex-col items-center gap-3">
      <div className="grid w-full max-w-[280px] grid-cols-3 grid-rows-3 gap-2.5">
        <div aria-hidden="true" />
        <CompassCell icon={ArrowUp} label="Langt" value={long} />
        <div aria-hidden="true" />
        <CompassCell icon={ArrowLeft} label="Venstre" value={left} />
        <div className="flex items-center justify-center">
          <div className="relative flex size-14 items-center justify-center rounded-full bg-primary/15">
            <div className="flex size-10 items-center justify-center rounded-full bg-primary/30">
              <Flag aria-hidden="true" className="size-5 text-primary" fill="currentColor" />
            </div>
          </div>
        </div>
        <CompassCell icon={ArrowRight} label="Høyre" value={right} />
        <div aria-hidden="true" />
        <CompassCell icon={ArrowDown} label="Kort" value={short} />
        <div aria-hidden="true" />
      </div>
      <p className="text-center text-xs text-muted-foreground">{trackedHoles} innspill registrert med retning.</p>
    </div>
  )
}

// --- Fairway: enklere venstre/fairway/høyre-bar (ingen langt/kort-akse
// fra utslaget, så ikke et fullt kompass) --------------------------------

function FairwayBar({
  tracked,
  left,
  hit,
  right,
}: {
  tracked: number
  left: number | null
  hit: number | null
  right: number | null
}) {
  if (tracked === 0) return <p className="text-sm text-muted-foreground">Ingen utslag registrert ennå.</p>
  const segments = [
    { label: "Venstre", value: left, color: "var(--brand-orange)" },
    { label: "Fairway", value: hit, color: "var(--primary)" },
    { label: "Høyre", value: right, color: "var(--brand-orange)" },
  ]
  return (
    <div className="flex flex-col gap-2">
      <div className="flex h-4 w-full overflow-hidden rounded-full bg-muted">
        {segments.map((s) =>
          s.value && s.value > 0 ? (
            <div key={s.label} style={{ width: `${s.value}%`, backgroundColor: s.color }} title={`${s.label}: ${Math.round(s.value)} %`} />
          ) : null,
        )}
      </div>
      <div className="flex flex-wrap gap-x-4 gap-y-1 text-sm text-muted-foreground">
        {segments.map((s) => (
          <span key={s.label} className="inline-flex items-center gap-1.5">
            <span aria-hidden="true" className="size-2.5 rounded-full" style={{ backgroundColor: s.color }} />
            {s.label}: <span className="font-semibold tabular-nums text-foreground">{s.value !== null ? pct(s.value) : "–"}</span>
          </span>
        ))}
      </div>
    </div>
  )
}

// --- Utvikling over tid: stolpegraf + trendlinje, per variabel ---------
// Brukerinstruks 2026-08-12: stolpe per runde (eldste til venstre) +
// trendlinje, for ALLE variabler -- ikke bare snitt til par. Tidligere
// bevisst UTSATT (se CHANGELOG 2026-07-28: "for lite rundehistorikk til
// å vise noe meningsfullt"), bygget da brukeren fikk nok runder.
//
// Trendlinjen er LINEÆR REGRESJON (minste kvadraters metode), ikke et
// glidende snitt -- brukeren påpekte (med rette) at et glidende snitt
// over så få runder bare gjentar stolpene med én runde forsinkelse. En
// rett regresjonslinje er visuelt og matematisk en helt annen form (en
// retning, ikke en kopi av dataene), og stigningstallet kan leses rett
// ut som "endring per runde" (se AskUserQuestion-svar 2026-08-12).
//
// Fargevalg: KUN snitt til par har en meningsfull 0-linje (par) å være
// diverging rundt (primary = på/under par, brand-orange = over par,
// samme par som `Delta` allerede bruker). De andre variablene er ren
// magnitude (prosent eller antall, alltid >= 0) og får én gjennomgående
// farge -- ingen kunstig "godt/dårlig"-deling der en slik deling ikke
// finnes i selve tallet.

const TREND_BAR_WIDTH = 20
const TREND_BAR_GAP = 10
const TREND_CHART_HEIGHT = 160
const TREND_HALF_HEIGHT = TREND_CHART_HEIGHT / 2 - 14 // plass til dato-etiketter under
const TREND_MAGNITUDE_HEIGHT = TREND_CHART_HEIGHT - 34 // baseline nederst, samme topp-marg

// Lineær regresjon (minste kvadraters metode) -- returnerer den rette
// linjens y-verdi ved hver indeks. Rendret som polyline blir dette
// bokstavelig talt en rett strek, ikke en linje som følger dataene.
function linearRegression(values: number[]): number[] {
  const n = values.length
  if (n === 0) return []
  const xMean = (n - 1) / 2
  const yMean = values.reduce((a, b) => a + b, 0) / n
  let num = 0
  let den = 0
  values.forEach((y, x) => {
    num += (x - xMean) * (y - yMean)
    den += (x - xMean) ** 2
  })
  const slope = den === 0 ? 0 : num / den
  const intercept = yMean - slope * xMean
  return values.map((_, x) => intercept + slope * x)
}

function formatShortDate(iso: string): string {
  const d = new Date(iso)
  return `${d.getDate()}.${d.getMonth() + 1}`
}

// Stolpe med avrundet ende BORTE fra 0-linjen, skarp kant VED 0-linjen --
// samme prinsipp uansett om verdien er over eller under par (dataviz-
// skillets "4px avrundet dataende, skarp ved grunnlinjen").
function barPath(x: number, valueY: number, baselineY: number, width: number, radius: number): string {
  const top = Math.min(valueY, baselineY)
  const bottom = Math.max(valueY, baselineY)
  const h = bottom - top
  if (h < radius) {
    // For kort til å avrunde pent -- vanlig rektangel.
    return `M ${x} ${top} H ${x + width} V ${bottom} H ${x} Z`
  }
  const roundedAtTop = valueY < baselineY
  if (roundedAtTop) {
    return `M ${x} ${top + radius} A ${radius} ${radius} 0 0 1 ${x + radius} ${top} H ${x + width - radius} A ${radius} ${radius} 0 0 1 ${x + width} ${top + radius} V ${bottom} H ${x} Z`
  }
  return `M ${x} ${top} H ${x + width} V ${bottom - radius} A ${radius} ${radius} 0 0 1 ${x + width - radius} ${bottom} H ${x + radius} A ${radius} ${radius} 0 0 1 ${x} ${bottom - radius} Z`
}

type TrendPoint = { played_at: string; value: number }

function BarTrendChart({
  points,
  mode,
  formatValue,
  formatSlope = formatValue,
  goodDirection,
  slopeSuffix,
  yAxisLabel,
}: {
  points: TrendPoint[]
  // "diverging": symmetrisk 0-linje midt i grafen, farge følger fortegn
  // (kun snitt til par). "magnitude": baseline nederst, alltid >= 0, én farge.
  mode: "diverging" | "magnitude"
  // Brukt på hver stolpes verdi-etikett/tooltip -- kan trygt ha egen enhet
  // (f.eks. "%") siden den står alene der.
  formatValue: (v: number) => string
  // Brukt KUN på stigningstallet i bildeteksten -- egen formatterer der
  // formatValue sin enhet ville kollidert med slopeSuffix (f.eks. "52 %"
  // + "pp per runde" ville blitt "52 % pp per runde"). Faller tilbake til
  // formatValue når det ikke kolliderer (f.eks. `signed`, som ikke har
  // noen enhet innebygd).
  formatSlope?: (v: number) => string
  goodDirection: "up" | "down"
  // Enhet på stigningstallet i bildeteksten, f.eks. "per runde" eller "pp per runde".
  slopeSuffix: string
  // Enhet for y-aksen (f.eks. "%", "Slag til par", "Antall") -- ekte HTML-
  // tekst over grafen, ikke roterte SVG-glyffer, så den skalerer med
  // brukerens skriftstørrelse (tilgjengelighetsregelen i CLAUDE.md).
  yAxisLabel: string
}) {
  if (points.length < 2) return null

  const values = points.map((p) => p.value)
  const trend = linearRegression(values)
  const slopePerRound = points.length > 1 ? trend[trend.length - 1] - trend[0] : 0
  const avgSlopePerRound = slopePerRound / (points.length - 1)
  const improving = goodDirection === "up" ? avgSlopePerRound > 0 : avgSlopePerRound < 0

  const baselineY = TREND_CHART_HEIGHT - 20
  let valueToY: (v: number) => number
  if (mode === "diverging") {
    const maxAbs = Math.max(...values.map((v) => Math.abs(v)), 1)
    const scale = TREND_HALF_HEIGHT / maxAbs
    valueToY = (v) => baselineY - v * scale
  } else {
    const maxVal = Math.max(...values, 1)
    const scale = TREND_MAGNITUDE_HEIGHT / maxVal
    valueToY = (v) => baselineY - v * scale
  }

  const width = points.length * (TREND_BAR_WIDTH + TREND_BAR_GAP) + TREND_BAR_GAP
  const barCenterX = (i: number) => TREND_BAR_GAP + i * (TREND_BAR_WIDTH + TREND_BAR_GAP) + TREND_BAR_WIDTH / 2
  const trendLinePoints = trend.map((v, i) => `${barCenterX(i)},${valueToY(v)}`).join(" ")

  return (
    <div className="flex flex-col gap-2">
      <span className="text-xs font-bold uppercase tracking-wide text-muted-foreground">{yAxisLabel}</span>
      <div className="overflow-x-auto">
        <svg
          role="img"
          aria-label={`${points.length} runder, fra ${formatShortDate(points[0].played_at)} til ${formatShortDate(points[points.length - 1].played_at)}. Trend: ${avgSlopePerRound >= 0 ? "+" : "−"}${formatSlope(Math.abs(avgSlopePerRound))} ${slopeSuffix}.`}
          viewBox={`0 0 ${width} ${TREND_CHART_HEIGHT}`}
          width={width}
          height={TREND_CHART_HEIGHT}
          className="block"
        >
          <line x1={0} y1={baselineY} x2={width} y2={baselineY} stroke="var(--border)" strokeWidth={1} />

          {points.map((point, i) => {
            const cx = barCenterX(i)
            const overPar = mode === "diverging" && point.value > 0
            const isLast = i === points.length - 1
            const isFirst = i === 0
            return (
              <g key={point.played_at + i}>
                <path
                  d={barPath(cx - TREND_BAR_WIDTH / 2, valueToY(point.value), baselineY, TREND_BAR_WIDTH, 4)}
                  fill={mode === "diverging" ? (overPar ? "var(--brand-orange)" : "var(--primary)") : "var(--primary)"}
                >
                  <title>
                    {formatShortDate(point.played_at)}: {formatValue(point.value)}
                  </title>
                </path>
                {/* Direkte etikett på FØRSTE og SISTE stolpe -- verdi i begge
                    ender så grafen kan leses uten en egen y-akse-skala (samme
                    prinsipp som CumulativeTrendLine allerede bruker). Første er
                    dempet (utgangspunkt), siste er uthevet (nåværende nivå). */}
                {(isFirst || isLast) && !(isFirst && isLast) && (
                  <text
                    x={cx}
                    y={valueToY(point.value) + (mode === "diverging" && !overPar ? 14 : -6)}
                    textAnchor="middle"
                    className={
                      isLast
                        ? "fill-foreground text-[11px] font-bold tabular-nums"
                        : "fill-muted-foreground text-[10px] font-semibold tabular-nums"
                    }
                  >
                    {formatValue(point.value)}
                  </text>
                )}
                {(i === 0 || i === points.length - 1 || i === Math.floor(points.length / 2)) && (
                  <text x={cx} y={TREND_CHART_HEIGHT - 4} textAnchor="middle" className="fill-muted-foreground text-[10px] font-semibold">
                    {formatShortDate(point.played_at)}
                  </text>
                )}
              </g>
            )
          })}

          <polyline points={trendLinePoints} fill="none" stroke="var(--muted-foreground)" strokeWidth={2} strokeDasharray="5 4" strokeLinecap="round" />
        </svg>
      </div>
      <div className="flex flex-wrap items-center gap-x-2 gap-y-1 text-xs font-semibold">
        <span className="inline-flex items-center gap-1.5 text-muted-foreground">
          <span aria-hidden="true" className="h-0.5 w-4 rounded-full" style={{ backgroundColor: "var(--muted-foreground)", opacity: 0.7 }} />
          Trend (lineær regresjon)
        </span>
        <span className={improving ? "text-primary" : "text-brand-orange"}>
          {avgSlopePerRound >= 0 ? "+" : "−"}
          {formatSlope(Math.abs(avgSlopePerRound))} {slopeSuffix}
        </span>
      </div>
    </div>
  )
}

function ScoreTrendChart({ series }: { series: ApiRoundSeriesPoint[] }) {
  const points = series.map((p) => ({ played_at: p.played_at, value: p.score_to_par }))
  if (points.length < 2) return null
  return (
    <Card title="Utvikling" subtitle="Snitt til par per runde, eldste runde til venstre.">
      <BarTrendChart points={points} mode="diverging" formatValue={signed} goodDirection="down" slopeSuffix="per runde" yAxisLabel="Slag til par" />
    </Card>
  )
}

// Generisk per-variabel-trend -- filtrerer bort runder uten data for
// akkurat DENNE metrikken (f.eks. en runde uten puttsporing), i stedet
// for å late som verdien var 0.
function seriesFor(series: ApiRoundSeriesPoint[], field: keyof ApiRoundSeriesPoint): TrendPoint[] {
  return series
    .filter((p) => p[field] !== null)
    .map((p) => ({ played_at: p.played_at, value: p[field] as number }))
}

// Kumulativ (ikke per-runde) linje for Scrambling/Sand save -- se
// AskUserQuestion-svar 2026-08-12: for få kvalifiserte hull per runde
// til at et per-runde-tall er meningsfullt, så her vises kun raten
// "til og med denne runden" som en enkel linje, ingen stolper.
function CumulativeTrendLine({
  points,
  label,
  yAxisLabel,
}: {
  points: TrendPoint[]
  label: string
  yAxisLabel: string
}) {
  if (points.length < 2) return null
  const values = points.map((p) => p.value)
  const maxVal = Math.max(...values, 1)
  const baselineY = TREND_CHART_HEIGHT - 20
  const scale = TREND_MAGNITUDE_HEIGHT / maxVal
  const valueToY = (v: number) => baselineY - v * scale
  const width = Math.max(points.length * 26, 160)
  const stepX = (i: number) => (points.length > 1 ? (i / (points.length - 1)) * (width - 24) + 12 : width / 2)
  const linePoints = points.map((p, i) => `${stepX(i)},${valueToY(p.value)}`).join(" ")

  return (
    <div className="flex flex-col gap-2">
      <span className="text-xs font-bold uppercase tracking-wide text-muted-foreground">{yAxisLabel}</span>
      <div className="overflow-x-auto">
        <svg
          role="img"
          aria-label={`${label}, kumulativt: ${Math.round(points[0].value)} % ved starten, ${Math.round(points[points.length - 1].value)} % nå.`}
          viewBox={`0 0 ${width} ${TREND_CHART_HEIGHT}`}
          width={width}
          height={TREND_CHART_HEIGHT}
          className="block"
        >
          <line x1={0} y1={baselineY} x2={width} y2={baselineY} stroke="var(--border)" strokeWidth={1} />
          <polyline points={linePoints} fill="none" stroke="var(--primary)" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" />
          {points.map((p, i) => (
            <circle key={p.played_at + i} cx={stepX(i)} cy={valueToY(p.value)} r={i === points.length - 1 ? 4 : 3} fill="var(--primary)">
              <title>
                {formatShortDate(p.played_at)}: {Math.round(p.value)} %
              </title>
            </circle>
          ))}
          <text x={stepX(0)} y={valueToY(points[0].value) - 10} textAnchor="start" className="fill-muted-foreground text-[10px] font-semibold">
            {Math.round(points[0].value)} %
          </text>
          <text
            x={stepX(points.length - 1)}
            y={valueToY(points[points.length - 1].value) - 10}
            textAnchor="end"
            className="fill-foreground text-[11px] font-bold tabular-nums"
          >
            {Math.round(points[points.length - 1].value)} %
          </text>
        </svg>
      </div>
      <p className="text-xs font-semibold text-muted-foreground">Kumulativt -- raten din til og med hver runde, ikke per-runde-tall.</p>
    </div>
  )
}

// --- Til par: med vs. uten en gitt hendelse på hullet -----------------------
// Brukerens eksplisitte instruks 2026-07-28: se snitt til par NÅR noe
// inntraff mot NÅR det ikke gjorde det (greentreff, fairwaytreff, bunker,
// anywayslag), i stedet for bare en isolert prosentandel. Fargen følger
// hvilken av de to som FAKTISK var lavest denne perioden (ikke en fast
// antakelse om hvilken side som "skal" være best), siden det er selve
// sammenligningen som er poenget.

function CompareToPar({
  title,
  aLabel,
  aValue,
  bLabel,
  bValue,
}: {
  title: string
  aLabel: string
  aValue: number | null
  bLabel: string
  bValue: number | null
}) {
  if (aValue === null && bValue === null) {
    return (
      <div>
        <h3 className="text-sm font-bold text-foreground">{title}</h3>
        <p className="text-sm text-muted-foreground">Ingen data registrert ennå.</p>
      </div>
    )
  }
  const aBetter = aValue !== null && bValue !== null && aValue < bValue
  const bBetter = aValue !== null && bValue !== null && bValue < aValue
  return (
    <div className="flex flex-col gap-2">
      <h3 className="text-sm font-bold text-foreground">{title}</h3>
      <div className="grid grid-cols-2 gap-3">
        <div className={`rounded-xl border p-3 ${aBetter ? "border-primary bg-primary/10" : "border-border bg-card"}`}>
          <span className="text-xs font-semibold text-muted-foreground">{aLabel}</span>
          <div className="text-xl font-extrabold tabular-nums text-foreground">{aValue !== null ? signed(aValue) : "–"}</div>
        </div>
        <div className={`rounded-xl border p-3 ${bBetter ? "border-primary bg-primary/10" : "border-border bg-card"}`}>
          <span className="text-xs font-semibold text-muted-foreground">{bLabel}</span>
          <div className="text-xl font-extrabold tabular-nums text-foreground">{bValue !== null ? signed(bValue) : "–"}</div>
        </div>
      </div>
    </div>
  )
}

export function RoundsStatsSummary() {
  const router = useRouter()
  const [window, setWindow] = useState<WindowKey>("all")
  const [data, setData] = useState<ApiWindowSummary | null>(null)
  const [error, setError] = useState<string | null>(null)

  useEffect(() => {
    let cancelled = false
    async function load() {
      try {
        const res = await fetch(`/rounds/stats/summary?window=${window}`, { credentials: "include" })
        if (res.status === 401) {
          router.replace("/logg-inn")
          return
        }
        if (!res.ok) throw new Error(`stats: ${res.status}`)
        const json: ApiWindowSummary = await res.json()
        if (!cancelled) setData(json)
      } catch {
        if (!cancelled) setError("Klarte ikke å hente statistikken. Prøv igjen om litt.")
      }
    }
    void load()
    return () => {
      cancelled = true
    }
  }, [router, window])

  const s = data?.current ?? 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/95 backdrop-blur">
        <div className="mx-auto flex min-h-14 max-w-xl items-center gap-2 px-4 py-2">
          <Link
            href="/dashboard"
            aria-label="Til dashbord"
            className="flex size-11 shrink-0 items-center justify-center rounded-xl text-muted-foreground transition-colors hover:bg-accent/50 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
          >
            <ArrowLeft aria-hidden="true" className="size-6" />
          </Link>
          <h1 className="text-lg font-extrabold tracking-tight text-foreground">Statistikk</h1>
        </div>
      </header>

      <main className="mx-auto flex w-full max-w-xl flex-1 flex-col gap-6 px-4 py-6 pb-16">
        <div className="flex gap-2 overflow-x-auto pb-1">
          {WINDOW_OPTIONS.map((opt) => (
            <button
              key={opt.key}
              type="button"
              onClick={() => setWindow(opt.key)}
              className={`min-h-11 shrink-0 rounded-full px-4 text-sm font-bold transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring ${
                window === opt.key ? "bg-primary text-primary-foreground" : "bg-muted text-foreground hover:bg-accent"
              }`}
            >
              {opt.label}
            </button>
          ))}
        </div>

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

        {data === null && !error ? (
          <div role="status" aria-live="polite" className="flex flex-col items-center justify-center gap-4 py-20 text-center">
            <div aria-hidden="true" className="size-9 animate-spin rounded-full border-4 border-primary/20 border-t-primary" />
            <span className="text-base font-medium text-muted-foreground">Laster statistikk…</span>
          </div>
        ) : s && s.rounds_completed === 0 ? (
          <div className="flex flex-col items-center gap-5 rounded-3xl border border-dashed border-border bg-card/50 px-6 py-16 text-center">
            <div className="flex size-16 items-center justify-center rounded-2xl bg-muted">
              <BarChart3 aria-hidden="true" className="size-8 text-muted-foreground" />
            </div>
            <div className="flex max-w-md flex-col gap-2">
              <h2 className="text-xl font-bold text-foreground">Ingen fullførte runder i perioden</h2>
              <p className="text-lg leading-relaxed text-muted-foreground text-pretty">
                Prøv et annet tidsvindu, eller kom tilbake etter neste fullførte runde.
              </p>
            </div>
          </div>
        ) : data ? (
          (() => {
            const s = data.current
            const p = data.previous
            const series = data.round_series
            const fairwayTrend = seriesFor(series, "fairway_hit_pct")
            const girTrend = seriesFor(series, "gir_pct")
            const puttsTrend = seriesFor(series, "putts_per_18")
            const onePuttTrend = seriesFor(series, "one_putt_pct")
            const chipTrend = seriesFor(series, "chip_per_round")
            const bunkerTrend = seriesFor(series, "bunker_per_round")
            const penaltyTrend = seriesFor(series, "penalty_per_round")
            const anywayTrend = seriesFor(series, "anyway_per_round")
            const scramblingCumulative = seriesFor(series, "scrambling_cumulative_pct")
            const sandSaveCumulative = seriesFor(series, "sand_save_cumulative_pct")
            return (
              <>
                <p className="text-base leading-relaxed text-muted-foreground text-pretty">
                  Aggregert over {s.rounds_completed} {s.rounds_completed === 1 ? "fullført runde" : "fullførte runder"}
                  {p.rounds_completed > 0 && (
                    <>
                      {" "}
                      · sammenlignet med {p.rounds_completed} {p.rounds_completed === 1 ? "runde" : "runder"} i perioden før
                    </>
                  )}
                  .
                </p>

                <Section title="Oversikt" icon={BarChart3}>
                  <StatTile label="Runder fullført" value={String(s.rounds_completed)} />
                  <StatTile
                    label="Snitt til par"
                    value={s.avg_score_to_par !== null ? signed(s.avg_score_to_par) : "–"}
                    delta={<Delta current={s.avg_score_to_par} previous={p.avg_score_to_par} format={signed} goodDirection="down" />}
                  />
                  <StatTile
                    label="Putt / 18 hull"
                    value={s.avg_putts_per_18 !== null ? s.avg_putts_per_18.toFixed(1).replace(".", ",") : "–"}
                    delta={<Delta current={s.avg_putts_per_18} previous={p.avg_putts_per_18} format={signed} goodDirection="down" />}
                    hint={
                      s.putts_tracked_rounds > 0
                        ? `${s.putts_tracked_rounds} ${s.putts_tracked_rounds === 1 ? "runde med" : "runder med"} puttsporing`
                        : "Ingen runder med puttsporing ennå"
                    }
                  />
                </Section>

                <ScoreTrendChart series={series} />

                {/* Rekkefølge 2026-08-12 (brukerinstruks): Utslag først, deretter
                    Greentreff (en beregnet andel), så Innspill (en retnings-
                    beskrivelse -- egen kortype av samme grunn som round-stats.tsx
                    skiller "Greentreff (GIR)" fra "Bom-retning på green"). Redning
                    og "Til par: med vs. uten" flyttet ned under Annet, se der. */}

                <Card title="Utslag" subtitle="Kun par 4/5, kun registrerte utslag.">
                  <FairwayBar tracked={s.fairway_tracked_holes} left={s.fairway_left_pct} hit={s.fairway_hit_pct} right={s.fairway_right_pct} />
                  <div className="flex items-center justify-between border-t border-border pt-3">
                    <span className="text-sm font-semibold text-muted-foreground">Fairwaytreff</span>
                    <Delta current={s.fairway_hit_pct} previous={p.fairway_hit_pct} format={signedPoints} goodDirection="up" />
                  </div>
                  {fairwayTrend.length >= 2 && (
                    <div className="border-t border-border pt-3">
                      <p className="mb-1 text-sm font-bold text-foreground">Fairwaytreff over tid</p>
                      <BarTrendChart
                        points={fairwayTrend}
                        mode="magnitude"
                        formatValue={pct}
                        formatSlope={roundedNoUnit}
                        goodDirection="up"
                        slopeSuffix="pp per runde"
                        yAxisLabel="%"
                      />
                    </div>
                  )}
                </Card>

                <Card title="Greentreff (GIR)" subtitle="Andel innspill som traff green i regulert antall slag.">
                  <GirGauge hitPct={s.gir_pct} trackedHoles={s.gir_tracked_holes} />
                  <div className="flex items-center justify-between border-t border-border pt-3">
                    <span className="text-sm font-semibold text-muted-foreground">Greentreff</span>
                    <Delta current={s.gir_pct} previous={p.gir_pct} format={signedPoints} goodDirection="up" />
                  </div>
                  {girTrend.length >= 2 && (
                    <div className="border-t border-border pt-3">
                      <p className="mb-1 text-sm font-bold text-foreground">Greentreff over tid</p>
                      <BarTrendChart points={girTrend} mode="magnitude" formatValue={pct} formatSlope={roundedNoUnit} goodDirection="up" slopeSuffix="pp per runde" yAxisLabel="%" />
                    </div>
                  )}
                </Card>

                <Card title="Innspill" subtitle="Retningen du bommer i, når du bommer greenen.">
                  <ApproachDirectionCompass
                    trackedHoles={s.green_miss_tracked_holes}
                    long={s.green_miss_long_pct}
                    short={s.green_miss_short_pct}
                    left={s.green_miss_left_pct}
                    right={s.green_miss_right_pct}
                  />
                </Card>

                <Card title="Putting">
                  <Donut
                    centerValue={s.avg_putts_per_18 !== null ? s.avg_putts_per_18.toFixed(1).replace(".", ",") : "–"}
                    centerLabel="putt / 18 hull"
                    segments={
                      s.putt_dist_one_pct !== null
                        ? [
                            { label: "1-putt", value: s.putt_dist_one_pct ?? 0, color: "var(--primary)" },
                            { label: "2-putt", value: s.putt_dist_two_pct ?? 0, color: "var(--info)" },
                            { label: "3-putt+", value: s.putt_dist_three_plus_pct ?? 0, color: "var(--brand-orange)" },
                          ]
                        : []
                    }
                  />
                  {s.putt_dist_one_pct === null && <p className="text-sm text-muted-foreground">Ingen puttfordeling registrert ennå.</p>}
                  <div className="flex items-center justify-between border-t border-border pt-3">
                    <span className="text-sm font-semibold text-muted-foreground">Én-putt</span>
                    <Delta current={s.one_putt_pct} previous={p.one_putt_pct} format={signedPoints} goodDirection="up" />
                  </div>
                  {puttsTrend.length >= 2 && (
                    <div className="border-t border-border pt-3">
                      <p className="mb-1 text-sm font-bold text-foreground">Putt / 18 hull over tid</p>
                      <BarTrendChart points={puttsTrend} mode="magnitude" formatValue={oneDecimal} goodDirection="down" slopeSuffix="putt per runde" yAxisLabel="Putt" />
                    </div>
                  )}
                  {onePuttTrend.length >= 2 && (
                    <div className="border-t border-border pt-3">
                      <p className="mb-1 text-sm font-bold text-foreground">Én-putt over tid</p>
                      <BarTrendChart points={onePuttTrend} mode="magnitude" formatValue={pct} formatSlope={roundedNoUnit} goodDirection="up" slopeSuffix="pp per runde" yAxisLabel="%" />
                    </div>
                  )}
                </Card>

                <Section title="Chip, bunker og straffeslag" icon={Waves}>
                  <StatTile
                    label="Chip / runde"
                    value={s.avg_chip_per_round !== null ? s.avg_chip_per_round.toFixed(1).replace(".", ",") : "–"}
                    delta={<Delta current={s.avg_chip_per_round} previous={p.avg_chip_per_round} format={signed} goodDirection="down" />}
                  />
                  <StatTile
                    label="Bunkerslag / runde"
                    value={s.avg_bunker_per_round !== null ? s.avg_bunker_per_round.toFixed(1).replace(".", ",") : "–"}
                    delta={<Delta current={s.avg_bunker_per_round} previous={p.avg_bunker_per_round} format={signed} goodDirection="down" />}
                  />
                  <StatTile
                    label="Straffeslag / runde"
                    value={s.avg_penalty_per_round !== null ? s.avg_penalty_per_round.toFixed(1).replace(".", ",") : "–"}
                    delta={<Delta current={s.avg_penalty_per_round} previous={p.avg_penalty_per_round} format={signed} goodDirection="down" />}
                  />
                </Section>

                {(chipTrend.length >= 2 || bunkerTrend.length >= 2 || penaltyTrend.length >= 2) && (
                  <Card title="Chip, bunker og straffeslag over tid">
                    {chipTrend.length >= 2 && (
                      <div>
                        <p className="mb-1 text-sm font-bold text-foreground">Chip / runde</p>
                        <BarTrendChart points={chipTrend} mode="magnitude" formatValue={oneDecimal} goodDirection="down" slopeSuffix="per runde" yAxisLabel="Antall" />
                      </div>
                    )}
                    {bunkerTrend.length >= 2 && (
                      <div className="border-t border-border pt-3">
                        <p className="mb-1 text-sm font-bold text-foreground">Bunkerslag / runde</p>
                        <BarTrendChart points={bunkerTrend} mode="magnitude" formatValue={oneDecimal} goodDirection="down" slopeSuffix="per runde" yAxisLabel="Antall" />
                      </div>
                    )}
                    {penaltyTrend.length >= 2 && (
                      <div className="border-t border-border pt-3">
                        <p className="mb-1 text-sm font-bold text-foreground">Straffeslag / runde</p>
                        <BarTrendChart points={penaltyTrend} mode="magnitude" formatValue={oneDecimal} goodDirection="down" slopeSuffix="per runde" yAxisLabel="Antall" />
                      </div>
                    )}
                  </Card>
                )}

                {s.avg_anyway_per_round !== null && (
                  <Section title="Annet" icon={Wind}>
                    <StatTile
                      label="Anywayslag / runde"
                      value={s.avg_anyway_per_round.toFixed(1).replace(".", ",")}
                      delta={<Delta current={s.avg_anyway_per_round} previous={p.avg_anyway_per_round} format={signed} goodDirection="down" />}
                    />
                  </Section>
                )}

                {anywayTrend.length >= 2 && (
                  <Card title="Anywayslag over tid">
                    <BarTrendChart points={anywayTrend} mode="magnitude" formatValue={oneDecimal} goodDirection="down" slopeSuffix="per runde" yAxisLabel="Antall" />
                  </Card>
                )}

                <Card title="Redning" subtitle="Par eller bedre etter en bom.">
                  <div className="grid grid-cols-2 gap-4">
                    <div className="flex flex-col items-center gap-2">
                      <Donut
                        size={104}
                        thickness={14}
                        showLegend={false}
                        centerValue={s.scrambling_pct !== null ? `${Math.round(s.scrambling_pct)}%` : "–"}
                        centerLabel=""
                        segments={s.scrambling_pct !== null ? [{ label: "Scrambling", value: s.scrambling_pct, color: "var(--primary)" }] : []}
                      />
                      <span className="text-sm font-bold text-foreground">Scrambling</span>
                      <Delta current={s.scrambling_pct} previous={p.scrambling_pct} format={signedPoints} goodDirection="up" />
                    </div>
                    <div className="flex flex-col items-center gap-2">
                      <Donut
                        size={104}
                        thickness={14}
                        showLegend={false}
                        centerValue={s.sand_save_pct !== null ? `${Math.round(s.sand_save_pct)}%` : "–"}
                        centerLabel=""
                        segments={s.sand_save_pct !== null ? [{ label: "Sand save", value: s.sand_save_pct, color: "var(--primary)" }] : []}
                      />
                      <span className="text-sm font-bold text-foreground">Sand save</span>
                      <Delta current={s.sand_save_pct} previous={p.sand_save_pct} format={signedPoints} goodDirection="up" />
                    </div>
                  </div>
                  {(scramblingCumulative.length >= 2 || sandSaveCumulative.length >= 2) && (
                    <div className="grid grid-cols-1 gap-4 border-t border-border pt-3 sm:grid-cols-2">
                      {scramblingCumulative.length >= 2 && (
                        <div>
                          <p className="mb-1 text-sm font-bold text-foreground">Scrambling over tid</p>
                          <CumulativeTrendLine points={scramblingCumulative} label="Scrambling" yAxisLabel="%" />
                        </div>
                      )}
                      {sandSaveCumulative.length >= 2 && (
                        <div>
                          <p className="mb-1 text-sm font-bold text-foreground">Sand save over tid</p>
                          <CumulativeTrendLine points={sandSaveCumulative} label="Sand save" yAxisLabel="%" />
                        </div>
                      )}
                    </div>
                  )}
                </Card>

                <Card title="Til par: med vs. uten" subtitle="Snitt til par på enkelthull, splittet på om noe faktisk inntraff.">
                  <CompareToPar
                    title="Greentreff (GIR)"
                    aLabel="Med GIR"
                    aValue={s.avg_to_par_with_gir}
                    bLabel="Uten GIR"
                    bValue={s.avg_to_par_without_gir}
                  />
                  <CompareToPar
                    title="Fairwaytreff"
                    aLabel="Traff fairway"
                    aValue={s.avg_to_par_fairway_hit}
                    bLabel="Bom fairway"
                    bValue={s.avg_to_par_fairway_miss}
                  />
                  <CompareToPar
                    title="Bunker"
                    aLabel="Ikke i bunker"
                    aValue={s.avg_to_par_without_bunker}
                    bLabel="I bunker"
                    bValue={s.avg_to_par_with_bunker}
                  />
                  <CompareToPar
                    title="Anywayslag"
                    aLabel="Uten anywayslag"
                    aValue={s.avg_to_par_without_anyway}
                    bLabel="Med anywayslag"
                    bValue={s.avg_to_par_with_anyway}
                  />
                </Card>
              </>
            )
          })()
        ) : null}
      </main>
    </div>
  )
}
