"use client"

// Dashbord-redesign (ADR-035, 2026-07-25): organisasjon er ikke lenger det
// første/viktigste en bruker møter -- en bruker er først og fremst en
// GOLFSPILLER. Presentasjon fra V0 (zip 18), datalag skrevet om fra mock
// til ekte fetch. Organisasjon-opprettelse er nå USYNLIG/automatisk ("Ny
// turnering" oppretter/gjenbruker en organisasjon i bakgrunnen, ingen eget
// "opprett organisasjon"-steg for det vanlige tilfellet) -- se
// ARCHITECTURE_DECISIONS.md ADR-035 Beslutning A.

import type React from "react"
import { useCallback, useEffect, useState } from "react"
import { useRouter } from "next/navigation"
import Link from "next/link"
import {
  ArrowRight,
  Bell,
  Building2,
  ChevronRight,
  Flag,
  KeyRound,
  LogOut,
  MapPin,
  Plus,
  TrendingDown,
  TrendingUp,
  Trophy,
  UserCircle,
  UserPlus,
  X,
} from "lucide-react"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import { Wordmark } from "@/components/wordmark"
import { RoundCard, type Round } from "@/components/round-card"
import { TournamentCard, type Tournament } from "@/components/tournament-card"
import { type TournamentStatus } from "@/components/tournament-status-badge"
import { cn } from "@/lib/utils"

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

type MyOrg = { organization_id: string; name: string; role: string }

// ADR-031: turneringer brukeren er SPILLER i (rostret på et lag), på tvers
// av organisasjoner, uavhengig av organisasjonsmedlemskap.
type MyTournament = {
  organization_id: string
  organization_name: string
  tournament_id: string
  tournament_name: string
  status: TournamentStatus
  team_id: string
  team_name: string
  team_color: string | null
  next_session_at: string | null
  my_session_id: string | null
  my_match_id: string | null
}

type Me = {
  id: string
  email: string
  display_name: string
  preferred_locale: string
  profile_complete: boolean
  handicap_index: number | null
  organizations: MyOrg[]
  my_tournaments: MyTournament[]
}

type ApiTournament = {
  id: string
  name: string
  status: TournamentStatus
  start_date: string | null
  end_date: string | null
}

type ApiRoundParticipant = { is_owner: boolean; counts_for_handicap: boolean; score_differential: number | null }
type ApiRound = {
  id: string
  name: string | null
  course_name_snapshot: string
  tee_name_snapshot: string
  played_at: string
  holes_planned: number
  completed_at: string | null
  participants: ApiRoundParticipant[]
  owner_holes_played: number
  owner_total_score: number | null
  owner_score_to_par: number | null
}

type ApiHandicapPoint = { handicap_index: number; recorded_at: string }

// ADR-036 fase 1 -- kun det dashbordets kompakte kort trenger (ikke hele
// GET /friends-responsen, som også bærer utgående forespørsler/kategorier).
type ApiFriendsSummary = {
  friends: { first_name: string | null; last_name: string | null }[]
  incoming_requests: unknown[]
}

function toTournament(t: ApiTournament): Tournament {
  return { id: t.id, name: t.name, status: t.status, startDate: t.start_date ?? undefined, endDate: t.end_date ?? undefined }
}

function toRound(r: ApiRound): Round {
  const owner = r.participants.find((p) => p.is_owner)
  return {
    id: r.id,
    name: r.name,
    courseName: r.course_name_snapshot,
    status: r.completed_at ? "completed" : "active",
    teeName: r.tee_name_snapshot,
    holes: r.holes_planned === 9 ? 9 : 18,
    date: r.played_at,
    playerCount: r.participants.length,
    holesPlayed: r.owner_holes_played,
    totalScore: r.owner_total_score ?? undefined,
    toPar: r.owner_score_to_par ?? undefined,
    differential: owner?.counts_for_handicap ? owner.score_differential : null,
  }
}

// --- Kombinert turnering-oppføring (deltaker OG/ELLER arrangør) ------------

type CombinedTournament = { tournament: Tournament; organizer: boolean; orgId: string; sortKey: string | null }

function combineTournaments(myTournaments: MyTournament[], organizerLists: { orgId: string; tournaments: ApiTournament[] }[]): CombinedTournament[] {
  const byId = new Map<string, CombinedTournament>()

  for (const t of myTournaments) {
    byId.set(t.tournament_id, {
      tournament: { id: t.tournament_id, name: t.tournament_name, status: t.status, startDate: t.next_session_at ?? undefined },
      organizer: false,
      orgId: t.organization_id,
      sortKey: t.next_session_at,
    })
  }

  for (const { orgId, tournaments } of organizerLists) {
    for (const t of tournaments) {
      const existing = byId.get(t.id)
      byId.set(t.id, {
        tournament: existing?.tournament ?? toTournament(t),
        organizer: true,
        orgId: existing?.orgId ?? orgId,
        sortKey: existing?.sortKey ?? t.start_date,
      })
    }
  }

  // Kun "kommende" -- fullførte/arkiverte turneringer skal ikke fylle opp
  // en "kommende"-liste, uansett dato.
  const upcoming = [...byId.values()].filter((c) => c.tournament.status === "draft" || c.tournament.status === "active")
  upcoming.sort((a, b) => {
    if (a.sortKey && b.sortKey) return a.sortKey < b.sortKey ? -1 : 1
    if (a.sortKey) return -1
    if (b.sortKey) return 1
    return a.tournament.name.localeCompare(b.tournament.name)
  })
  return upcoming
}

// --- Formattering ------------------------------------------------------------

function formatSigned(value: number, decimals = 1): string {
  if (value === 0) return decimals === 0 ? "0" : `0,${"0".repeat(decimals)}`
  const abs = Math.abs(value).toFixed(decimals).replace(".", ",")
  return value > 0 ? `+${abs}` : `−${abs}`
}

const dateFormatter = new Intl.DateTimeFormat("no-NO", { day: "numeric", month: "short", year: "numeric" })
function formatDate(value: string) {
  const parsed = new Date(value)
  if (Number.isNaN(parsed.getTime())) return value
  return dateFormatter.format(parsed)
}

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

export function Dashboard() {
  const router = useRouter()
  const [me, setMe] = useState<Me | null>(null)
  const [loadingMe, setLoadingMe] = useState(true)
  const [rounds, setRounds] = useState<ApiRound[] | null>(null)
  const [combinedTournaments, setCombinedTournaments] = useState<CombinedTournament[]>([])
  const [hcpHistory, setHcpHistory] = useState<ApiHandicapPoint[]>([])
  const [friendsSummary, setFriendsSummary] = useState<ApiFriendsSummary | null>(null)
  const [unreadNotifications, setUnreadNotifications] = useState(0)
  const [error, setError] = useState<string | null>(null)

  const loadMe = useCallback(async () => {
    try {
      const res = await fetch("/auth/me", { credentials: "include" })
      if (!res.ok) {
        router.replace("/")
        return
      }
      const data: Me = await res.json()
      if (!data.profile_complete) {
        router.replace("/account")
        return
      }
      setMe(data)
    } catch {
      router.replace("/")
    } finally {
      setLoadingMe(false)
    }
  }, [router])

  useEffect(() => {
    void loadMe()
  }, [loadMe])

  useEffect(() => {
    fetch("/rounds", { credentials: "include" })
      .then((res) => (res.ok ? res.json() : []))
      .then((data: ApiRound[]) => setRounds(data))
      .catch(() => setRounds([]))
    fetch("/auth/profile/handicap-history", { credentials: "include" })
      .then((res) => (res.ok ? res.json() : []))
      .then((data: ApiHandicapPoint[]) => setHcpHistory(data))
      .catch(() => {})
    fetch("/friends", { credentials: "include" })
      .then((res) => (res.ok ? res.json() : null))
      .then((data: ApiFriendsSummary | null) => setFriendsSummary(data))
      .catch(() => {})
    fetch("/notifications/unread-count", { credentials: "include" })
      .then((res) => (res.ok ? res.json() : { count: 0 }))
      .then((data: { count: number }) => setUnreadNotifications(data.count))
      .catch(() => {})
  }, [])

  useEffect(() => {
    if (!me) return
    let cancelled = false
    async function loadOrganizerTournaments() {
      try {
        const lists = await Promise.all(
          me!.organizations.map(async (o) => {
            const res = await fetch(`/orgs/${o.organization_id}/tournaments`, { credentials: "include" })
            const tournaments: ApiTournament[] = res.ok ? await res.json() : []
            return { orgId: o.organization_id, tournaments }
          }),
        )
        if (!cancelled) setCombinedTournaments(combineTournaments(me!.my_tournaments, lists))
      } catch {
        if (!cancelled) setCombinedTournaments(combineTournaments(me!.my_tournaments, []))
      }
    }
    void loadOrganizerTournaments()
    return () => {
      cancelled = true
    }
  }, [me])

  // "Ny turnering": organisasjon opprettes/gjenbrukes USYNLIG (ADR-035) --
  // ingen egen "opprett organisasjon"-skjerm for det vanlige tilfellet.
  // Har brukeren INGEN organisasjon, genereres et navn og POST /orgs kalles
  // FØRST ved selve innsendingen (ikke når skjemaet bare åpnes -- unngår en
  // foreldreløs tom org hvis brukeren avbryter).
  async function handleCreateTournament(name: string, chosenOrgId: string | null) {
    if (!me) return
    setError(null)
    try {
      let orgId = chosenOrgId ?? (me.organizations.length === 1 ? me.organizations[0].organization_id : null)
      if (!orgId) {
        const orgName = me.display_name ? `${me.display_name}s turneringer` : "Mine turneringer"
        const orgRes = await fetch("/orgs", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          credentials: "include",
          body: JSON.stringify({ name: orgName }),
        })
        if (!orgRes.ok) throw new Error("orgs")
        const org: { id: string; name: string; role: string } = await orgRes.json()
        orgId = org.id
        setMe((prev) => (prev ? { ...prev, organizations: [...prev.organizations, { organization_id: org.id, name: org.name, role: org.role }] } : prev))
      }
      const res = await fetch(`/orgs/${orgId}/tournaments`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        credentials: "include",
        body: JSON.stringify({ name }),
      })
      if (!res.ok) throw new Error("create tournament")
      const created: ApiTournament = await res.json()
      router.push(`/tournaments/${created.id}?org=${orgId}&name=${encodeURIComponent(created.name)}`)
    } catch {
      setError("Klarte ikke å opprette turneringen. Prøv igjen.")
    }
  }

  async function handleLogout() {
    try {
      await fetch("/auth/logout", { method: "POST", credentials: "include" })
    } finally {
      router.replace("/")
    }
  }

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

  if (!me) return null // router.replace("/") er allerede utløst

  const rows = rounds ?? []
  const activeRounds = rows.filter((r) => !r.completed_at)
  const completedRounds = rows.filter((r) => r.completed_at)
  const roundsForCards = activeRounds.length > 0 ? activeRounds : rows.slice(0, 3)

  const avgToParSample = completedRounds
    .filter((r) => r.owner_score_to_par !== null)
    .slice(0, 5)
    .map((r) => r.owner_score_to_par as number)
  const avgToPar = avgToParSample.length > 0 ? formatSigned(avgToParSample.reduce((s, v) => s + v, 0) / avgToParSample.length, 1) : "—"

  const hcpValues = hcpHistory.map((h) => h.handicap_index)
  const hcpTrend = hcpValues.length >= 2 ? hcpValues[hcpValues.length - 1] - hcpValues[hcpValues.length - 2] : null
  const hcpNow = me.handicap_index !== null ? me.handicap_index.toFixed(1).replace(".", ",") : "—"

  const coursesMap = new Map<string, { name: string; visits: number; lastPlayed: string }>()
  for (const r of rows) {
    const existing = coursesMap.get(r.course_name_snapshot)
    if (existing) {
      existing.visits += 1
      if (r.played_at > existing.lastPlayed) existing.lastPlayed = r.played_at
    } else {
      coursesMap.set(r.course_name_snapshot, { name: r.course_name_snapshot, visits: 1, lastPlayed: r.played_at })
    }
  }
  const playedCourses = [...coursesMap.values()].sort((a, b) => (a.lastPlayed < b.lastPlayed ? 1 : -1))

  return (
    <div className="flex min-h-[100dvh] flex-col bg-background">
      <header className="sticky top-0 z-10 border-b border-border bg-background/80 backdrop-blur">
        <div className="mx-auto flex w-full max-w-3xl items-center justify-between gap-4 px-5 py-4">
          <Wordmark compact />
          <div className="flex items-center gap-1">
            <NotificationBell unreadCount={unreadNotifications} />
            <Link
              href="/account"
              className="inline-flex min-h-[44px] items-center gap-1.5 rounded-lg px-2 py-1.5 text-sm font-semibold text-muted-foreground transition-colors hover:text-foreground"
            >
              <UserCircle aria-hidden="true" className="size-4" />
              Konto
            </Link>
            <button
              type="button"
              onClick={handleLogout}
              className="inline-flex min-h-[44px] items-center gap-1.5 rounded-lg px-2 py-1.5 text-sm font-semibold text-muted-foreground transition-colors hover:text-foreground"
            >
              <LogOut aria-hidden="true" className="size-4" />
              Logg ut
            </button>
          </div>
        </div>
      </header>

      <main className="mx-auto w-full max-w-3xl flex-1 px-5 pb-16 pt-6 sm:pt-8">
        <div className="flex flex-col gap-2">
          <h1 className="text-2xl font-extrabold tracking-tight text-foreground text-balance">
            God dag, {me.display_name}
          </h1>
          <p className="text-base leading-relaxed text-muted-foreground text-pretty">
            Klar for en ny runde? Her er golfen din på ett sted.
          </p>
        </div>

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

        <div className="mt-6 flex flex-col gap-8">
          <QuickActions organizations={me.organizations} onCreateTournament={handleCreateTournament} />
          <UpcomingRounds rounds={roundsForCards.map(toRound)} loading={rounds === null} />
          <UpcomingTournaments entries={combinedTournaments} />
          <StatsSection roundsCount={rows.length} hcpNow={hcpNow} hcpTrend={hcpTrend} hcpHistory={hcpValues} avgToPar={avgToPar} />
          <PlayedCourses courses={playedCourses} />
          <FriendsSection summary={friendsSummary} />
          <OrganizationsFooter organizations={me.organizations} />
        </div>
      </main>
    </div>
  )
}

// V0-designet (varsler-runden, 2026-07-25) -- lenker til /my-notifications,
// IKKE /notifications (API-prefiks, samme kollisjonsklasse som
// /rounds->/my-rounds og /friends->/my-friends).
function NotificationBell({ unreadCount }: { unreadCount: number }) {
  const hasUnread = unreadCount > 0
  const label = hasUnread ? `Varsler, ${unreadCount} uleste` : "Varsler, ingen uleste"
  const badgeText = unreadCount > 9 ? "9+" : String(unreadCount)

  return (
    <Link
      href="/my-notifications"
      aria-label={label}
      className="relative inline-flex size-11 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
    >
      <Bell aria-hidden="true" className="size-5" />
      {hasUnread && (
        <span
          aria-hidden="true"
          className="absolute right-1 top-1 flex min-w-[18px] items-center justify-center rounded-full bg-brand-orange px-1 text-[11px] font-bold leading-none text-brand-orange-foreground ring-2 ring-background"
          style={{ height: 18 }}
        >
          {badgeText}
        </span>
      )}
    </Link>
  )
}

// --- 1. Hurtighandlinger -----------------------------------------------------

function QuickActions({
  organizations,
  onCreateTournament,
}: {
  organizations: MyOrg[]
  onCreateTournament: (name: string, orgId: string | null) => Promise<void>
}) {
  const [open, setOpen] = useState<"tournament" | "code" | null>(null)

  return (
    <section aria-label="Hurtighandlinger" className="flex flex-col gap-3">
      <div className="grid grid-cols-1 gap-3 sm:grid-cols-3">
        <QuickAction icon={Flag} label="Ny runde" href="/my-rounds/new" />
        <QuickAction icon={Trophy} label="Ny turnering" onClick={() => setOpen(open === "tournament" ? null : "tournament")} />
        <QuickAction icon={KeyRound} label="Bli med med kode" onClick={() => setOpen(open === "code" ? null : "code")} />
      </div>
      {open === "tournament" && (
        <NewTournamentInline organizations={organizations} onCreate={onCreateTournament} onClose={() => setOpen(null)} />
      )}
      {open === "code" && <JoinByCodeInline onClose={() => setOpen(null)} />}
    </section>
  )
}

function QuickAction({
  icon: Icon,
  label,
  href,
  onClick,
}: {
  icon: typeof Flag
  label: string
  href?: string
  onClick?: () => void
}) {
  const className =
    "flex min-h-[108px] flex-1 flex-col items-center justify-center gap-2.5 rounded-2xl border border-border bg-card p-4 text-center shadow-sm shadow-black/5 transition-colors hover:border-primary/60 hover:bg-accent/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background"
  const inner = (
    <>
      <span className="flex size-12 items-center justify-center rounded-xl bg-primary/15 text-primary">
        <Icon aria-hidden="true" className="size-6" />
      </span>
      <span className="text-sm font-bold leading-tight text-foreground text-balance">{label}</span>
    </>
  )
  if (href) {
    return (
      <Link href={href} className={className}>
        {inner}
      </Link>
    )
  }
  return (
    <button type="button" onClick={onClick} className={className}>
      {inner}
    </button>
  )
}

function NewTournamentInline({
  organizations,
  onCreate,
  onClose,
}: {
  organizations: MyOrg[]
  onCreate: (name: string, orgId: string | null) => Promise<void>
  onClose: () => void
}) {
  const [name, setName] = useState("")
  const [orgId, setOrgId] = useState(organizations[0]?.organization_id ?? "")
  const [submitting, setSubmitting] = useState(false)
  const valid = name.trim().length >= 2

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault()
    if (!valid || submitting) return
    setSubmitting(true)
    await onCreate(name.trim(), organizations.length > 1 ? orgId : null)
    setSubmitting(false)
  }

  return (
    <form onSubmit={handleSubmit} className="flex flex-col gap-3 rounded-2xl border border-border bg-card p-4 shadow-sm shadow-black/5 sm:flex-row sm:items-end">
      <div className="flex flex-1 flex-col gap-1.5">
        <Label htmlFor="new-tournament-name" className="text-sm font-semibold">
          Navn på turnering
        </Label>
        <Input
          id="new-tournament-name"
          autoFocus
          placeholder="F.eks. Sommercup 2026"
          value={name}
          onChange={(e) => setName(e.target.value)}
          className="h-11 rounded-xl"
        />
      </div>
      {organizations.length > 1 && (
        <div className="flex flex-col gap-1.5">
          <Label htmlFor="new-tournament-org" className="text-sm font-semibold">
            Organisasjon
          </Label>
          <select
            id="new-tournament-org"
            value={orgId}
            onChange={(e) => setOrgId(e.target.value)}
            className="h-11 rounded-xl border border-border bg-card px-3 text-sm font-medium text-foreground outline-none sm:w-48"
          >
            {organizations.map((o) => (
              <option key={o.organization_id} value={o.organization_id}>
                {o.name}
              </option>
            ))}
          </select>
        </div>
      )}
      <div className="flex gap-2">
        <Button type="submit" disabled={!valid || submitting} className="h-11 rounded-xl font-bold">
          {submitting ? "Oppretter…" : "Opprett"}
        </Button>
        <Button type="button" variant="ghost" size="icon" onClick={onClose} className="size-11 rounded-xl text-muted-foreground" aria-label="Avbryt">
          <X aria-hidden="true" className="size-5" />
        </Button>
      </div>
    </form>
  )
}

function JoinByCodeInline({ onClose }: { onClose: () => void }) {
  const router = useRouter()
  const [code, setCode] = useState("")
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState<string | null>(null)

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault()
    const trimmed = code.trim()
    if (!trimmed || loading) return
    setLoading(true)
    setError(null)
    try {
      const res = await fetch(`/public/tournaments/by-code/${encodeURIComponent(trimmed)}`)
      if (!res.ok) {
        const body = await res.json().catch(() => null)
        setError(body?.detail?.message ?? "Fant ingen turnering med denne koden.")
        return
      }
      const data: { tournament_id: string } = await res.json()
      router.push(`/t/${data.tournament_id}?code=${encodeURIComponent(trimmed)}`)
    } catch {
      setError("Klarte ikke å slå opp koden. Prøv igjen.")
    } finally {
      setLoading(false)
    }
  }

  return (
    <form onSubmit={handleSubmit} className="flex flex-col gap-3 rounded-2xl border border-border bg-card p-4 shadow-sm shadow-black/5 sm:flex-row sm:items-end">
      <div className="flex flex-1 flex-col gap-1.5">
        <Label htmlFor="join-code-inline" className="text-sm font-semibold">
          Invitasjonskode
        </Label>
        <Input
          id="join-code-inline"
          autoFocus
          placeholder="F.eks. 7K2M9P"
          value={code}
          onChange={(e) => setCode(e.target.value.toUpperCase())}
          className="h-11 rounded-xl uppercase tracking-widest"
        />
        {error && <p className="text-sm font-medium text-destructive">{error}</p>}
      </div>
      <div className="flex gap-2">
        <Button type="submit" disabled={!code.trim() || loading} className="h-11 rounded-xl font-bold">
          {loading ? "Søker…" : "Bli med"}
        </Button>
        <Button type="button" variant="ghost" size="icon" onClick={onClose} className="size-11 rounded-xl text-muted-foreground" aria-label="Avbryt">
          <X aria-hidden="true" className="size-5" />
        </Button>
      </div>
    </form>
  )
}

// --- Delt seksjon-"chrome" ----------------------------------------------------

function SectionHeader({ title, action }: { title: string; action?: React.ReactNode }) {
  return (
    <div className="mb-3 flex items-center justify-between gap-3">
      <h2 className="text-lg font-extrabold tracking-tight text-foreground">{title}</h2>
      {action}
    </div>
  )
}

function SeeAllLink({ href, label }: { href: string; label: string }) {
  return (
    <Link
      href={href}
      className="inline-flex min-h-[44px] items-center gap-1 rounded-lg px-2 text-sm font-bold text-primary transition-colors hover:bg-accent/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
    >
      {label}
      <ChevronRight aria-hidden="true" className="size-4" />
    </Link>
  )
}

function EmptyState({
  icon: Icon,
  title,
  description,
  children,
}: {
  icon: typeof Flag
  title: string
  description: string
  children?: React.ReactNode
}) {
  return (
    <div className="flex flex-col items-center gap-3 rounded-2xl border border-dashed border-border bg-card/50 px-6 py-8 text-center">
      <div className="flex size-12 items-center justify-center rounded-xl bg-muted">
        <Icon aria-hidden="true" className="size-6 text-muted-foreground" />
      </div>
      <div className="flex flex-col gap-1">
        <h3 className="text-base font-bold text-foreground text-balance">{title}</h3>
        <p className="text-sm leading-relaxed text-muted-foreground text-pretty">{description}</p>
      </div>
      {children ? <div className="mt-1 flex flex-wrap justify-center gap-2">{children}</div> : null}
    </div>
  )
}

function ShortcutButton({
  icon: Icon,
  label,
  href,
  variant = "primary",
}: {
  icon: typeof Flag
  label: string
  href?: string
  variant?: "primary" | "outline"
}) {
  const className = cn(
    "inline-flex min-h-[44px] items-center gap-1.5 rounded-xl px-4 text-sm font-bold transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
    variant === "primary" ? "bg-primary text-primary-foreground shadow-sm hover:bg-primary/90" : "border border-border bg-card text-foreground hover:bg-accent/50",
  )
  const inner = (
    <>
      <Icon aria-hidden="true" className="size-4" />
      {label}
    </>
  )
  if (href) {
    return (
      <Link href={href} className={className}>
        {inner}
      </Link>
    )
  }
  return (
    <button type="button" className={className}>
      {inner}
    </button>
  )
}

// --- 2. Kommende runder --------------------------------------------------------

function UpcomingRounds({ rounds, loading }: { rounds: Round[]; loading: boolean }) {
  const visible = rounds.slice(0, 3)
  return (
    <section aria-label="Kommende runder">
      <SectionHeader title="Kommende runder" action={rounds.length > 0 ? <SeeAllLink href="/my-rounds" label="Se alle" /> : null} />
      {loading ? (
        <div className="flex justify-center py-8">
          <div aria-hidden="true" className="size-8 animate-spin rounded-full border-4 border-primary/20 border-t-primary" />
        </div>
      ) : visible.length > 0 ? (
        <div className="flex flex-col gap-3">
          {visible.map((round) => (
            <RoundCard key={round.id} round={round} />
          ))}
        </div>
      ) : (
        <EmptyState icon={Flag} title="Ingen runder på gang" description="Start en runde når du er på banen, så dukker den opp her mens du spiller.">
          <ShortcutButton icon={Plus} label="Ny runde" href="/my-rounds/new" />
        </EmptyState>
      )}
    </section>
  )
}

// --- 3. Kommende turneringer -----------------------------------------------

function UpcomingTournaments({ entries }: { entries: CombinedTournament[] }) {
  return (
    <section aria-label="Kommende turneringer">
      <SectionHeader title="Kommende turneringer" />
      {entries.length > 0 ? (
        <div className="flex flex-col gap-3">
          {entries.map((e) => (
            <TournamentCard key={e.tournament.id} tournament={e.tournament} orgId={e.orgId} organizer={e.organizer} />
          ))}
        </div>
      ) : (
        <EmptyState icon={Trophy} title="Ingen turneringer ennå" description="Bli med i en turnering med en kode fra arrangøren, eller opprett din egen.">
          <ShortcutButton icon={Trophy} label="Ny turnering" />
          <ShortcutButton icon={KeyRound} label="Bli med med kode" variant="outline" />
        </EmptyState>
      )}
    </section>
  )
}

// --- 4. Statistikk ---------------------------------------------------------

function Sparkline({ values }: { values: number[] }) {
  if (values.length < 2) return null
  const max = Math.max(...values)
  const min = Math.min(...values)
  const range = max - min || 1
  return (
    <div aria-hidden="true" className="flex h-5 items-end gap-0.5">
      {values.map((v, i) => {
        const height = 30 + ((v - min) / range) * 70
        return <div key={i} className="w-1 rounded-full bg-primary/40" style={{ height: `${height}%` }} />
      })}
    </div>
  )
}

function StatTile({ label, value, children }: { label: string; value: string; children?: React.ReactNode }) {
  return (
    <div className="flex flex-col gap-1.5 rounded-2xl border border-border bg-card p-4 shadow-sm shadow-black/5">
      <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>
      {children}
    </div>
  )
}

function StatsSection({
  roundsCount,
  hcpNow,
  hcpTrend,
  hcpHistory,
  avgToPar,
}: {
  roundsCount: number
  hcpNow: string
  hcpTrend: number | null
  hcpHistory: number[]
  avgToPar: string
}) {
  const TrendIcon = hcpTrend !== null && hcpTrend < 0 ? TrendingDown : TrendingUp
  return (
    <section aria-label="Statistikk">
      <SectionHeader title="Statistikk" />
      <div className="grid grid-cols-3 gap-3">
        <StatTile label="Runder" value={String(roundsCount)} />
        <StatTile label="HCP nå" value={hcpNow}>
          {hcpTrend !== null ? (
            <div className="flex items-center justify-between gap-1">
              <span className="inline-flex items-center gap-1 text-xs font-bold text-foreground">
                <TrendIcon aria-hidden="true" className="size-4 text-primary" />
                <span className="tabular-nums">{formatSigned(hcpTrend, 1)}</span>
                <span className="sr-only">{hcpTrend < 0 ? "handicap gått ned" : "handicap gått opp"}</span>
              </span>
              <Sparkline values={hcpHistory} />
            </div>
          ) : (
            <span className="text-xs font-medium text-muted-foreground">Ingen data</span>
          )}
        </StatTile>
        <StatTile label="Snitt til par" value={avgToPar} />
      </div>
    </section>
  )
}

// --- 5. Spilte baner ---------------------------------------------------------

function PlayedCourses({ courses }: { courses: { name: string; visits: number; lastPlayed: string }[] }) {
  return (
    <section aria-label="Spilte baner">
      <SectionHeader title="Spilte baner" />
      {courses.length > 0 ? (
        <ul className="flex flex-col divide-y divide-border overflow-hidden rounded-2xl border border-border bg-card">
          {courses.map((course) => {
            const roundLabel = course.visits === 1 ? "runde" : "runder"
            return (
              <li key={course.name} className="flex min-h-[60px] items-center gap-3 px-4 py-3">
                <span className="flex size-10 shrink-0 items-center justify-center rounded-xl bg-primary/15 text-primary">
                  <MapPin aria-hidden="true" className="size-5" />
                </span>
                <span className="flex min-w-0 flex-1 flex-col">
                  <span className="truncate text-base font-bold text-foreground">{course.name}</span>
                  <span className="truncate text-sm text-muted-foreground">
                    {course.visits} {roundLabel} · Sist {formatDate(course.lastPlayed)}
                  </span>
                </span>
              </li>
            )
          })}
        </ul>
      ) : (
        <EmptyState icon={MapPin} title="Ingen baner registrert" description="Banene du spiller dukker opp her, med antall besøk og når du sist spilte." />
      )}
    </section>
  )
}

// --- 6. Venner ---------------------------------------------------------------
// ADR-036 fase 1 (venner-kjernen) er live -- ekte data fra GET /friends.

function friendInitials(first: string | null, last: string | null): string {
  const f = (first ?? "").trim()[0] ?? ""
  const l = (last ?? "").trim()[0] ?? ""
  return (f + l).toUpperCase() || "?"
}

function FriendsSection({ summary }: { summary: ApiFriendsSummary | null }) {
  const friends = summary?.friends ?? []
  const pending = summary?.incoming_requests.length ?? 0

  return (
    <section aria-label="Venner">
      <SectionHeader title="Venner" />
      {friends.length > 0 ? (
        <div className="flex flex-col gap-4 rounded-2xl border border-border bg-card p-4 shadow-sm shadow-black/5 sm:flex-row sm:items-center sm:justify-between">
          <div className="flex items-center gap-3">
            <div className="flex items-center">
              {friends.slice(0, 4).map((friend, i) => (
                <span
                  key={i}
                  className={cn(
                    "flex size-11 items-center justify-center rounded-full border-2 border-card bg-primary/15 text-sm font-bold text-foreground",
                    i > 0 && "-ml-3",
                  )}
                >
                  {friendInitials(friend.first_name, friend.last_name)}
                </span>
              ))}
            </div>
            <div className="flex flex-col">
              <span className="text-base font-bold text-foreground">
                {friends.length} {friends.length === 1 ? "venn" : "venner"}
              </span>
              {pending > 0 ? (
                <span className="inline-flex w-fit items-center gap-1.5 rounded-full bg-brand-orange/15 px-2.5 py-0.5 text-xs font-bold text-foreground">
                  <span aria-hidden="true" className="size-1.5 rounded-full bg-brand-orange" />
                  {pending} ventende {pending === 1 ? "forespørsel" : "forespørsler"}
                </span>
              ) : (
                <span className="text-sm text-muted-foreground">Ingen nye forespørsler</span>
              )}
            </div>
          </div>
          <ShortcutButton icon={ArrowRight} label="Se venner" href="/my-friends" variant="outline" />
        </div>
      ) : (
        <EmptyState icon={UserPlus} title="Finn vennene dine" description="Søk opp folk du spiller med, så kan dere følge hverandres runder og resultater.">
          <ShortcutButton icon={UserPlus} label="Søk etter venner" href="/my-friends" />
        </EmptyState>
      )}
    </section>
  )
}

// --- 7. Organisasjoner (bevisst nedtonet) -----------------------------------

function OrganizationsFooter({ organizations }: { organizations: MyOrg[] }) {
  const router = useRouter()
  if (organizations.length === 0) return null
  return (
    <div className="flex justify-center pt-2">
      <DropdownMenu>
        <DropdownMenuTrigger className="inline-flex min-h-[44px] items-center gap-1.5 rounded-lg px-3 text-sm font-medium text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring">
          <Building2 aria-hidden="true" className="size-4" />
          Dine organisasjoner ({organizations.length})
        </DropdownMenuTrigger>
        <DropdownMenuContent align="center" className="w-64 rounded-2xl p-1.5">
          {organizations.map((o) => (
            <DropdownMenuItem
              key={o.organization_id}
              onClick={() => router.push(`/organizations/${o.organization_id}/members?name=${encodeURIComponent(o.name)}`)}
              className="cursor-pointer rounded-xl px-3 py-2.5 text-sm font-semibold"
            >
              {o.name}
            </DropdownMenuItem>
          ))}
        </DropdownMenuContent>
      </DropdownMenu>
    </div>
  )
}
