"use client"

// Horisontalt scorekort for en frittstående runde (ADR-033) -- egen,
// dedikert side (ikke en del av round-stats.tsx sin aggregerte statistikk).
// Presentasjon fra V0 (zip 17), datalag skrevet om fra mock til ekte fetch
// mot samme `/rounds/{id}/participants/{id}/holes`-endepunkt som
// round-detail.tsx og round-stats.tsx allerede bruker.
//
// Bevisst forskjell fra V0s eksport: V0s egen `strokesReceived()` var en
// generisk modulo-formel -- byttet ut med backend sin ALLEREDE beregnede
// `strokes_received` per hull (samme `allocate_strokes_by_index()`-
// algoritme som resten av appen), for å unngå to ulike implementasjoner av
// samme HCP-slagfordeling.

import { useEffect, useState } from "react"
import Link from "next/link"
import { ArrowLeft } from "lucide-react"
import { cn } from "@/lib/utils"

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

type ApiParticipant = {
  id: string
  guest_name: string | null
  is_owner: boolean
}

type ApiRound = {
  name: string | null
  id: string
  course_name_snapshot: string
  tee_name_snapshot: string
  played_at: string
  start_hole: number
  holes_planned: number
  participants: ApiParticipant[]
}

type ApiHole = {
  hole_number: number
  par: number
  stroke_index: number
  played: boolean
  score: number | null
  strokes_received: number | null
}

const dateFormatter = new Intl.DateTimeFormat("no-NO", { day: "numeric", month: "long", year: "numeric" })

function participantLabel(p: ApiParticipant): string {
  return p.is_owner ? "Deg" : (p.guest_name ?? "Gjest")
}

// --- Scoring helpers -------------------------------------------------------

function netScore(h: ApiHole): number | null {
  return h.played && h.score !== null && h.strokes_received !== null ? h.score - h.strokes_received : null
}

// Stableford: 2 pts for net par, +/- 1 per stroke, floored at 0.
function stablefordPoints(h: ApiHole): number | null {
  const net = netScore(h)
  if (net === null) return null
  return Math.max(0, h.par - net + 2)
}

type ScoreClass = "eagle" | "birdie" | "par" | "bogey" | "double"

function classify(gross: number, par: number): ScoreClass {
  const diff = gross - par
  if (diff <= -2) return "eagle"
  if (diff === -1) return "birdie"
  if (diff === 0) return "par"
  if (diff === 1) return "bogey"
  return "double"
}

function sum(values: number[]): number {
  return values.reduce((a, b) => a + b, 0)
}

function signedToPar(score: number, par: number): string {
  const diff = score - par
  if (diff === 0) return "E"
  return diff > 0 ? `+${diff}` : `−${Math.abs(diff)}`
}

// --- Score mark (the visual language for the Score row) --------------------
// Shape encodes direction (circle = under par, square = over par) so meaning
// survives without color; fill encodes magnitude (filled = 2+ strokes off).

function ScoreMark({ gross, par }: { gross: number | null; par: number }) {
  const shared =
    "flex size-6 items-center justify-center text-sm font-extrabold tabular-nums sm:size-7"
  if (gross === null) {
    return <span className={cn(shared, "text-muted-foreground")}>{"–"}</span>
  }
  const kind = classify(gross, par)
  if (kind === "eagle") {
    return (
      <span className={cn(shared, "rounded-full bg-primary text-primary-foreground")}>{gross}</span>
    )
  }
  if (kind === "birdie") {
    return (
      <span className={cn(shared, "rounded-full border-2 border-primary bg-primary/10 text-primary")}>
        {gross}
      </span>
    )
  }
  if (kind === "bogey") {
    return (
      <span
        className={cn(
          shared,
          "rounded-[4px] border-2 border-brand-orange bg-brand-orange/10 text-brand-orange",
        )}
      >
        {gross}
      </span>
    )
  }
  if (kind === "double") {
    return (
      <span className={cn(shared, "rounded-[4px] bg-brand-orange text-brand-orange-foreground")}>
        {gross}
      </span>
    )
  }
  // par
  return <span className={cn(shared, "font-bold text-foreground")}>{gross}</span>
}

// --- One nine-hole block (a real table for row/column semantics) -----------

function ScoreBlock({
  holes,
  summaryLabel,
  showStableford,
}: {
  holes: ApiHole[]
  summaryLabel: string
  showStableford: boolean
}) {
  const parSum = sum(holes.map((h) => h.par))
  const playedHoles = holes.filter((h) => h.played && h.score !== null)
  const grossSum = playedHoles.length > 0 ? sum(playedHoles.map((h) => h.score as number)) : null
  const nettoValues = holes.map(netScore).filter((n): n is number => n !== null)
  const nettoSum = nettoValues.length > 0 ? sum(nettoValues) : null
  const pointsValues = holes.map(stablefordPoints).filter((n): n is number => n !== null)
  const pointsSum = pointsValues.length > 0 ? sum(pointsValues) : null

  const cell = "border border-border text-center tabular-nums"
  const sumCell = "border border-border bg-muted text-center font-extrabold tabular-nums"
  const rowLabel =
    "border border-border px-1 text-left text-xs font-bold text-muted-foreground"

  return (
    <table className="w-full table-fixed border-collapse">
      <caption className="sr-only">
        Scorekort hull {holes[0].hole_number} til {holes[holes.length - 1].hole_number}
      </caption>
      <colgroup>
        <col className="w-9" />
        {holes.map((h) => (
          <col key={h.hole_number} />
        ))}
        <col className="w-[11%]" />
      </colgroup>
      <thead>
        <tr>
          <th scope="col" className="border border-border bg-muted px-1 py-1 text-left">
            <span className="sr-only">Rad</span>
            <span aria-hidden="true" className="text-xs font-extrabold text-muted-foreground">
              Hull
            </span>
          </th>
          {holes.map((h) => (
            <th
              key={h.hole_number}
              scope="col"
              className="border border-border bg-foreground py-1 text-center text-xs font-extrabold tabular-nums text-background"
            >
              {h.hole_number}
            </th>
          ))}
          <th
            scope="col"
            className="border border-border bg-primary py-1 text-center text-xs font-extrabold uppercase text-primary-foreground"
          >
            {summaryLabel}
          </th>
        </tr>
      </thead>
      <tbody>
        {/* Hcp (stroke index) */}
        <tr>
          <th scope="row" className={rowLabel}>
            Hcp
          </th>
          {holes.map((h) => (
            <td key={h.hole_number} className={cn(cell, "py-1 text-xs font-semibold text-muted-foreground")}>
              {h.stroke_index}
            </td>
          ))}
          <td className={cn(sumCell, "py-1 text-xs text-muted-foreground")} aria-hidden="true">
            {"–"}
          </td>
        </tr>
        {/* Par */}
        <tr>
          <th scope="row" className={rowLabel}>
            Par
          </th>
          {holes.map((h) => (
            <td key={h.hole_number} className={cn(cell, "py-1 text-xs font-semibold text-muted-foreground")}>
              {h.par}
            </td>
          ))}
          <td className={cn(sumCell, "py-1 text-xs text-foreground")}>{parSum}</td>
        </tr>
        {/* Score — the hero row: highlighted band + shape marks */}
        <tr className="bg-primary/5">
          <th scope="row" className={cn(rowLabel, "text-sm text-foreground")}>
            Score
          </th>
          {holes.map((h) => (
            <td key={h.hole_number} className={cn(cell, "px-0.5 py-1")}>
              <span className="flex items-center justify-center">
                <ScoreMark gross={h.played ? h.score : null} par={h.par} />
              </span>
            </td>
          ))}
          <td className={cn(sumCell, "py-1 text-base text-foreground")}>{grossSum ?? "–"}</td>
        </tr>
        {/* Netto */}
        <tr>
          <th scope="row" className={cn(rowLabel, "text-foreground")}>
            Netto
          </th>
          {holes.map((h) => (
            <td key={h.hole_number} className={cn(cell, "py-1 text-xs font-bold text-foreground")}>
              {netScore(h) ?? "–"}
            </td>
          ))}
          <td className={cn(sumCell, "py-1 text-xs text-foreground")}>{nettoSum ?? "–"}</td>
        </tr>
        {/* Stableford (only when relevant) */}
        {showStableford && (
          <tr>
            <th scope="row" className={rowLabel} title="Stableford-poeng">
              Poeng
            </th>
            {holes.map((h) => (
              <td key={h.hole_number} className={cn(cell, "py-1 text-xs font-semibold text-muted-foreground")}>
                {stablefordPoints(h) ?? "–"}
              </td>
            ))}
            <td className={cn(sumCell, "py-1 text-xs text-foreground")}>{pointsSum ?? "–"}</td>
          </tr>
        )}
      </tbody>
    </table>
  )
}

// --- Legend ----------------------------------------------------------------

function Legend() {
  return (
    <div
      className="flex flex-wrap items-center gap-x-4 gap-y-2 rounded-2xl border border-border bg-card px-4 py-3"
      aria-label="Symbolforklaring"
    >
      <span className="flex items-center gap-2">
        <span className="flex size-6 items-center justify-center rounded-full border-2 border-primary bg-primary/10 text-xs font-extrabold text-primary">
          3
        </span>
        <span className="text-sm font-semibold text-foreground">Under par (sirkel)</span>
      </span>
      <span className="flex items-center gap-2">
        <span className="flex size-6 items-center justify-center rounded-[4px] border-2 border-brand-orange bg-brand-orange/10 text-xs font-extrabold text-brand-orange">
          5
        </span>
        <span className="text-sm font-semibold text-foreground">Over par (firkant)</span>
      </span>
      <span className="text-sm font-medium text-muted-foreground">Fylt symbol = 2 slag eller mer</span>
    </div>
  )
}

// --- Combined total --------------------------------------------------------

function TotalTile({ label, value, tone }: { label: string; value: string; tone?: "orange" | "green" }) {
  return (
    <div className="flex flex-col items-center gap-0.5 rounded-2xl border border-border bg-card px-2 py-3">
      <span
        className={cn(
          "text-2xl font-extrabold tabular-nums",
          tone === "orange" ? "text-brand-orange" : tone === "green" ? "text-primary" : "text-foreground",
        )}
      >
        {value}
      </span>
      <span className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">{label}</span>
    </div>
  )
}

// --- Screen ----------------------------------------------------------------

export function RoundScorecard({ roundId }: { roundId: string }) {
  const [round, setRound] = useState<ApiRound | null>(null)
  const [participantId, setParticipantId] = useState<string | null>(null)
  const [holes, setHoles] = useState<ApiHole[] | null>(null)
  const [error, setError] = useState<string | null>(null)

  useEffect(() => {
    let cancelled = false
    async function load() {
      const res = await fetch(`/rounds/${roundId}`, { credentials: "include" })
      if (res.status === 403 || res.status === 404) {
        if (!cancelled) setError("Denne runden finnes ikke, eller du har ikke tilgang til den.")
        return
      }
      if (!res.ok) {
        if (!cancelled) setError("Klarte ikke å hente runden. Prøv igjen om litt.")
        return
      }
      const data: ApiRound = await res.json()
      if (cancelled) return
      setRound(data)
      setParticipantId(data.participants.find((p) => p.is_owner)?.id ?? data.participants[0]?.id ?? null)
    }
    void load()
    return () => {
      cancelled = true
    }
  }, [roundId])

  useEffect(() => {
    if (!participantId) return
    let cancelled = false
    async function loadHoles() {
      const res = await fetch(`/rounds/${roundId}/participants/${participantId}/holes`, { credentials: "include" })
      if (!res.ok) return
      const data: ApiHole[] = await res.json()
      if (!cancelled) setHoles(data)
    }
    void loadHoles()
    return () => {
      cancelled = true
    }
  }, [roundId, participantId])

  if (error) {
    return (
      <div className="flex min-h-dvh flex-col items-center justify-center gap-4 bg-background px-5 text-center">
        <p className="text-base font-medium text-destructive">{error}</p>
        <Link href="/my-rounds" className="text-base font-semibold text-primary underline underline-offset-2">
          Tilbake til egne runder
        </Link>
      </div>
    )
  }

  if (!round || !holes) {
    return (
      <div className="flex min-h-dvh flex-col items-center justify-center bg-background">
        <div aria-hidden="true" className="size-10 animate-spin rounded-full border-4 border-primary/20 border-t-primary" />
      </div>
    )
  }

  // Samme sirkulære start_hole-rekkefølge som round-detail.tsx/round-stats.tsx
  // -- "Ut"/"Inn" er dermed første/andre halvdel AV SPILLEREKKEFØLGEN, ikke
  // nødvendigvis fysisk hull 1-9/10-18 (relevant kun for en 18-hulls runde
  // med et annet starthull enn 1, uvanlig men strukturelt tillatt).
  const holeOrder = Array.from(
    { length: round.holes_planned },
    (_, i) => ((round.start_hole - 1 + i) % 18) + 1,
  )
  const orderedHoles = holeOrder
    .map((n) => holes.find((h) => h.hole_number === n))
    .filter((h): h is ApiHole => h !== undefined)
  const front = orderedHoles.slice(0, 9)
  const back = orderedHoles.slice(9, 18)

  const showStableford = holes.some((h) => h.strokes_received !== null)
  const playedHoles = orderedHoles.filter((h) => h.played && h.score !== null)
  const totalPar = sum(orderedHoles.map((h) => h.par))
  const totalGross = playedHoles.length > 0 ? sum(playedHoles.map((h) => h.score as number)) : null
  const totalPointsValues = orderedHoles.map(stablefordPoints).filter((n): n is number => n !== null)
  const totalPoints = totalPointsValues.length > 0 ? sum(totalPointsValues) : null

  return (
    <div className="min-h-dvh bg-background">
      {/* Header */}
      <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={`/my-rounds/${roundId}`}
            className="flex min-h-11 items-center gap-1.5 rounded-xl pr-3 text-base font-bold text-foreground transition-colors hover:text-primary"
          >
            <ArrowLeft aria-hidden="true" className="size-6" />
            Scorekort
          </Link>
        </div>
      </header>

      <main className="mx-auto flex max-w-xl flex-col gap-4 px-4 py-5 pb-16">
        {/* Round summary strip */}
        <div className="flex flex-wrap items-baseline justify-between gap-2 rounded-3xl border border-border bg-card p-4 shadow-sm shadow-black/5">
          <div className="flex flex-col">
            <span className="text-xl font-extrabold tracking-tight text-foreground text-balance">
              {round.name?.trim() || round.course_name_snapshot}
            </span>
            <span className="text-sm font-semibold text-muted-foreground">
              {round.name?.trim() ? `${round.course_name_snapshot} · ` : ""}
              {round.tee_name_snapshot} {"·"} {round.holes_planned} hull {"·"}{" "}
              {dateFormatter.format(new Date(round.played_at))}
            </span>
          </div>
          {totalGross !== null && (
            <div className="flex flex-col items-end">
              <span className="text-3xl font-extrabold tabular-nums text-foreground">{totalGross}</span>
              <span className="text-sm font-bold text-brand-orange">{signedToPar(totalGross, totalPar)} til par</span>
            </div>
          )}
        </div>

        {/* Spillervelger, kun når runden har flere deltakere */}
        {round.participants.length > 1 && (
          <div role="tablist" aria-label="Velg spiller" className="-mx-4 overflow-x-auto px-4">
            <div className="flex gap-2">
              {round.participants.map((p) => {
                const active = p.id === participantId
                return (
                  <button
                    key={p.id}
                    type="button"
                    role="tab"
                    aria-selected={active}
                    onClick={() => {
                      setHoles(null)
                      setParticipantId(p.id)
                    }}
                    className={cn(
                      "flex min-h-11 shrink-0 items-center rounded-2xl border px-4 text-base font-bold transition-colors",
                      active
                        ? "border-primary bg-primary text-primary-foreground"
                        : "border-border bg-card text-foreground hover:bg-accent/50",
                    )}
                  >
                    {participantLabel(p)}
                  </button>
                )
              })}
            </div>
          </div>
        )}

        {/* Legend */}
        <Legend />

        {/* Scorecard blocks */}
        <div className="flex flex-col gap-3 rounded-3xl border border-border bg-card p-3 shadow-sm shadow-black/5 sm:p-4">
          {front.length > 0 && (
            <ScoreBlock holes={front} summaryLabel={back.length === 0 ? "Tot" : "Ut"} showStableford={showStableford} />
          )}
          {back.length > 0 && <ScoreBlock holes={back} summaryLabel="Inn" showStableford={showStableford} />}
        </div>

        {/* Combined total */}
        <div className={cn("grid gap-2", showStableford ? "grid-cols-4" : "grid-cols-3")}>
          <TotalTile label="Par" value={String(totalPar)} />
          <TotalTile label="Score" value={totalGross !== null ? String(totalGross) : "–"} />
          <TotalTile
            label="Til par"
            value={totalGross !== null ? signedToPar(totalGross, totalPar) : "–"}
            tone="orange"
          />
          {showStableford && <TotalTile label="Poeng" value={totalPoints !== null ? String(totalPoints) : "–"} tone="green" />}
        </div>
      </main>
    </div>
  )
}
