"use client"

// Individuell rangering PER ØKT i en org-turnering (FEATURE_BACKLOG.md
// "Leaderboard for runder og turneringer", avklart 2026-07-28 -- omfang
// bevisst AVGRENSET til én økt, ikke summert på tvers av turneringen, se
// CLAUDE.md for begrunnelse). Ved siden av, ikke i stedet for, det
// eksisterende lag-poeng-leaderboardet (tournament-leaderboard.tsx) -- KUN
// meningsfullt for scoring_mode='stroke'-økter i format singles/fourball,
// backend avviser (400) ellers.
//
// Gjenbruker samme rangering/mode-toggle/verdi-merke-mønster som
// round-leaderboard.tsx (brutto/netto/poeng, "form + farge"-språket, delt
// plassering "T-N") -- egen, enklere lokal versjon her siden denne
// leaderboardet ikke har noen hull-for-hull-data å utvide til (backend
// returnerer kun aggregerte tall per deltaker, ikke per hull).

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

type ApiEntry = {
  participant_id: string
  display_name: string
  team_id: string
  team_name: string
  team_color: string | null
  thru: number
  gross_score: number | null
  gross_to_par: number | null
  net_score: number | null
  net_to_par: number | null
  total_points: number | null
}

type ApiLeaderboard = {
  session_id: string
  format: string
  entries: ApiEntry[]
}

const FORMAT_LABELS: Record<string, string> = {
  singles: "Singles",
  fourball: "Fourball",
}

type Mode = "gross" | "net" | "points"

type RankedEntry = ApiEntry & { rank: number | null; tied: boolean }

function valueFor(entry: ApiEntry, mode: Mode): number | null {
  if (mode === "gross") return entry.gross_to_par
  if (mode === "net") return entry.net_to_par
  return entry.total_points
}

function rankEntries(entries: ApiEntry[], mode: Mode): RankedEntry[] {
  const withValue = entries.filter((e) => valueFor(e, mode) !== null)
  const withoutValue = entries.filter((e) => valueFor(e, mode) === null)
  const direction = mode === "points" ? -1 : 1
  withValue.sort((a, b) => direction * ((valueFor(a, mode) as number) - (valueFor(b, mode) as number)))

  const ranked: RankedEntry[] = []
  let rank = 0
  let prevValue: number | null = null
  for (let i = 0; i < withValue.length; i++) {
    const e = withValue[i]
    const v = valueFor(e, mode) as number
    if (v !== prevValue) {
      rank = i + 1
      prevValue = v
    }
    const tied = withValue.filter((o) => valueFor(o, mode) === v).length > 1
    ranked.push({ ...e, rank, tied })
  }
  for (const e of withoutValue) {
    ranked.push({ ...e, rank: null, tied: false })
  }
  return ranked
}

function formatToPar(value: number): string {
  if (value === 0) return "E"
  return value > 0 ? `+${value}` : `−${Math.abs(value)}`
}

function ToParMark({ value, emphasize }: { value: number; emphasize: boolean }) {
  if (value === 0) {
    return <span className="text-lg font-extrabold tabular-nums text-foreground">E</span>
  }
  const under = value < 0
  return (
    <span
      className={cn(
        "flex h-10 min-w-10 shrink-0 items-center justify-center px-2 text-base font-extrabold tabular-nums",
        under ? "rounded-full" : "rounded-[6px]",
        emphasize
          ? under
            ? "bg-primary text-primary-foreground"
            : "bg-brand-orange text-brand-orange-foreground"
          : under
            ? "border-2 border-primary bg-primary/10 text-primary"
            : "border-2 border-brand-orange bg-brand-orange/10 text-brand-orange",
      )}
    >
      {formatToPar(value)}
    </span>
  )
}

function PointsMark({ value, emphasize }: { value: number; emphasize: boolean }) {
  return (
    <span
      className={cn(
        "flex h-10 min-w-10 shrink-0 items-center justify-center rounded-full px-2 text-base font-extrabold tabular-nums",
        emphasize ? "bg-primary text-primary-foreground" : "border-2 border-primary bg-primary/10 text-primary",
      )}
    >
      {value}
    </span>
  )
}

function ValueMark({ mode, value, emphasize }: { mode: Mode; value: number; emphasize: boolean }) {
  return mode === "points" ? <PointsMark value={value} emphasize={emphasize} /> : <ToParMark value={value} emphasize={emphasize} />
}

function RankBadge({ rank, tied, isLeader }: { rank: number | null; tied: boolean; isLeader: boolean }) {
  return (
    <span
      className={cn(
        "flex size-10 shrink-0 items-center justify-center rounded-full text-sm font-extrabold tabular-nums",
        isLeader ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground",
      )}
      aria-hidden="true"
    >
      {rank !== null ? (tied ? `T-${rank}` : `#${rank}`) : "–"}
    </span>
  )
}

function ModeToggle({ mode, onChange }: { mode: Mode; onChange: (m: Mode) => void }) {
  const options: { value: Mode; label: string }[] = [
    { value: "gross", label: "Brutto" },
    { value: "net", label: "Netto" },
    { value: "points", label: "Poeng" },
  ]
  return (
    <div role="tablist" aria-label="Brutto, netto eller poeng" className="inline-flex gap-1 rounded-full bg-muted p-1">
      {options.map((opt) => (
        <button
          key={opt.value}
          type="button"
          role="tab"
          aria-selected={mode === opt.value}
          onClick={() => onChange(opt.value)}
          className={cn(
            "min-h-9 rounded-full px-3.5 text-sm font-bold transition-colors",
            mode === opt.value ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:text-foreground",
          )}
        >
          {opt.label}
        </button>
      ))}
    </div>
  )
}

export function SessionIndividualLeaderboard({
  organizationId,
  tournamentId,
  sessionId,
  tournamentName,
}: {
  organizationId: string
  tournamentId: string
  sessionId: string
  tournamentName: string
}) {
  const [data, setData] = useState<ApiLeaderboard | null>(null)
  const [error, setError] = useState<string | null>(null)
  const [mode, setMode] = useState<Mode>("gross")

  useEffect(() => {
    let cancelled = false
    async function load() {
      const res = await fetch(`/orgs/${organizationId}/sessions/${sessionId}/individual-leaderboard`, {
        credentials: "include",
      })
      if (res.status === 400) {
        if (!cancelled)
          setError("Denne økten støtter ikke individuell rangering -- kun slagspill i format singles eller fourball.")
        return
      }
      if (res.status === 404) {
        if (!cancelled) setError("Økten finnes ikke.")
        return
      }
      if (!res.ok) {
        if (!cancelled) setError("Klarte ikke å hente rangeringen. Prøv igjen om litt.")
        return
      }
      const parsed: ApiLeaderboard = await res.json()
      if (!cancelled) setData(parsed)
    }
    void load()
    return () => {
      cancelled = true
    }
  }, [organizationId, sessionId])

  const backHref = `/tournaments/${tournamentId}/sessions/${sessionId}?org=${organizationId}&name=${encodeURIComponent(tournamentName)}`

  if (error) {
    return (
      <div className="flex min-h-[100dvh] 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={backHref} className="text-base font-semibold text-primary underline underline-offset-2">
          Tilbake til økten
        </Link>
      </div>
    )
  }

  if (!data) {
    return (
      <div className="flex min-h-[100dvh] 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>
    )
  }

  const ranked = rankEntries(data.entries, mode)

  return (
    <div className="min-h-[100dvh] 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={backHref}
            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" />
            Individuell rangering
          </Link>
        </div>
      </header>

      <main className="mx-auto flex max-w-xl flex-col gap-4 px-4 py-5 pb-16">
        <div className="flex flex-col gap-1 rounded-3xl border border-border bg-card p-4 shadow-sm shadow-black/5">
          <span className="text-xl font-extrabold tracking-tight text-foreground text-balance">{tournamentName}</span>
          <span className="text-sm font-semibold text-muted-foreground">{FORMAT_LABELS[data.format] ?? data.format}</span>
        </div>

        {data.entries.length === 0 ? (
          <p className="rounded-2xl border border-dashed border-border bg-card p-4 text-sm text-muted-foreground">
            Ingen deltakere å rangere ennå -- enten er ingen matcher satt opp, eller oppstillingen er ikke avslørt.
          </p>
        ) : (
          <>
            <div className="flex items-center justify-between gap-3">
              <h2 className="text-base font-bold text-foreground">Stilling</h2>
              <ModeToggle mode={mode} onChange={setMode} />
            </div>

            <ul className="divide-y divide-border overflow-hidden rounded-2xl border border-border bg-card">
              {ranked.map((entry) => {
                const value = valueFor(entry, mode)
                const isLeader = entry.rank === 1
                return (
                  <li key={entry.participant_id} className="flex items-center gap-3 p-3 sm:p-4">
                    <RankBadge rank={entry.rank} tied={entry.tied} isLeader={isLeader} />
                    <span
                      aria-hidden="true"
                      className="size-2.5 shrink-0 rounded-full"
                      style={{ backgroundColor: entry.team_color ?? "var(--muted-foreground)" }}
                    />
                    <span className="flex min-w-0 flex-1 flex-col">
                      <span className="truncate text-base font-bold text-foreground">{entry.display_name}</span>
                      <span className="truncate text-xs font-semibold text-muted-foreground">
                        {entry.team_name} · {entry.thru > 0 ? `${entry.thru} hull spilt` : "Ikke startet"}
                      </span>
                    </span>
                    {isLeader && entry.rank === 1 && <Trophy aria-hidden="true" className="size-4 shrink-0 text-primary" />}
                    {value !== null ? (
                      <ValueMark mode={mode} value={value} emphasize={isLeader} />
                    ) : (
                      <span className="shrink-0 text-sm font-semibold text-muted-foreground">–</span>
                    )}
                  </li>
                )
              })}
            </ul>

            {mode !== "gross" && ranked.some((e) => e.rank === null) && (
              <p className="text-sm text-muted-foreground">
                Spillere uten {mode === "net" ? "netto-tall" : "poengsum"} (ingen handicap beregnet ennå) vises uten
                rangering.
              </p>
            )}
          </>
        )}
      </main>
    </div>
  )
}
