"use client"

import type React from "react"
import { useEffect, useMemo, useRef, useState, type CSSProperties } from "react"
import { Download, Printer, Scissors } from "lucide-react"
import { cn } from "@/lib/utils"
import {
  fetchMatches,
  fetchRoundGroups,
  fetchRoundParticipants,
  fetchRounds,
  fetchSessions,
  fetchTeams,
  fetchTournament,
  fetchTournamentParticipants,
  type ApiMatch,
  type ApiRound,
  type ApiRoundParticipant,
  type ApiSession,
  type ApiTeam,
  type ApiTournamentParticipant,
} from "@/lib/print-data"

/**
 * Print-friendly CART TAGS -- ekte data (ADR-097). Videreført fra
 * V0-mockupen: 6 tags per ark (2×3 portrett / 3×2 landskap), stiplede
 * klippelinjer. Individuell: én tag per utslagsgruppe. Cup: én tag per
 * match (begge lags spillere på samme tag, lagfarge som markør).
 */

type PaperSize = "a4" | "letter"
type Orientation = "portrait" | "landscape"
const PAPER_MM: Record<PaperSize, { w: number; h: number; label: string }> = {
  a4: { w: 210, h: 297, label: "A4" },
  letter: { w: 216, h: 279, label: "Letter" },
}
const PX_PER_MM = 3.7795

type TagPlayer = { name: string; hcp: string; className: string; teamName?: string; teamColor?: string }
type TagGroup = { cart: number; teeTime: string; startHole: number; players: TagPlayer[] }

function Field({ label, hint, children }: { label: string; hint?: string; children: React.ReactNode }) {
  return (
    <div className="flex flex-col gap-2">
      <p className="text-xs font-bold uppercase tracking-wide text-muted-foreground">{label}</p>
      {children}
      {hint && <p className="text-xs leading-relaxed text-muted-foreground">{hint}</p>}
    </div>
  )
}

function Segmented({
  ariaLabel,
  value,
  onChange,
  options,
}: {
  ariaLabel: string
  value: string
  onChange: (v: string) => void
  options: { value: string; label: string; disabled?: boolean }[]
}) {
  return (
    <div role="radiogroup" aria-label={ariaLabel} className="flex rounded-xl border border-border bg-muted/40 p-1">
      {options.map((opt) => {
        const active = opt.value === value
        return (
          <button
            key={opt.value}
            type="button"
            role="radio"
            aria-checked={active}
            disabled={opt.disabled}
            onClick={() => onChange(opt.value)}
            className={cn(
              "flex-1 rounded-lg px-2 py-1.5 text-sm font-bold transition-colors",
              "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background",
              active ? "bg-primary text-primary-foreground shadow-sm" : "text-muted-foreground hover:text-foreground",
              opt.disabled && "cursor-not-allowed opacity-40 hover:text-muted-foreground",
            )}
          >
            {opt.label}
          </button>
        )
      })}
    </div>
  )
}

function Toggle({ label, hint, checked, onChange, disabled }: { label: string; hint?: string; checked: boolean; onChange: (v: boolean) => void; disabled?: boolean }) {
  return (
    <label className={cn("flex cursor-pointer items-center justify-between gap-3 py-3", disabled && "cursor-not-allowed opacity-50")}>
      <span className="flex flex-col">
        <span className="text-sm font-semibold text-foreground">{label}</span>
        {hint && <span className="text-xs leading-relaxed text-muted-foreground">{hint}</span>}
      </span>
      <button
        type="button"
        role="switch"
        aria-checked={checked && !disabled}
        disabled={disabled}
        onClick={() => onChange(!checked)}
        className={cn("relative h-6 w-11 shrink-0 rounded-full transition-colors", checked && !disabled ? "bg-primary" : "bg-muted-foreground/30")}
      >
        <span className={cn("absolute top-0.5 size-5 rounded-full bg-white shadow transition-transform", checked && !disabled ? "translate-x-[22px]" : "translate-x-0.5")} />
      </button>
    </label>
  )
}

function CartTag({
  group,
  tournamentName,
  showHcp,
  showStartHole,
  showClass,
  showTeams,
  showHeader,
}: {
  group: TagGroup
  tournamentName: string
  showHcp: boolean
  showStartHole: boolean
  showClass: boolean
  showTeams: boolean
  showHeader: boolean
}) {
  const startElsewhere = showStartHole && group.startHole !== 1
  return (
    <div className="flex h-full flex-col" style={{ padding: 6 * PX_PER_MM }}>
      {showHeader && (
        <p className="truncate font-semibold uppercase tracking-wide text-neutral-500" style={{ fontSize: 11 }}>
          {tournamentName}
        </p>
      )}
      <div className="flex items-start justify-between gap-2" style={{ marginTop: showHeader ? 2 : 0 }}>
        <div className="flex items-baseline gap-2 leading-none">
          <span className="font-semibold uppercase text-neutral-500" style={{ fontSize: 13 }}>
            Cart
          </span>
          <span className="font-black leading-none" style={{ fontSize: 68 }}>
            {group.cart}
          </span>
        </div>
        <div className="flex flex-col items-end leading-none">
          <span className="font-semibold uppercase text-neutral-500" style={{ fontSize: 11 }}>
            Utslag
          </span>
          <span className="font-black tabular-nums" style={{ fontSize: 26 }}>
            {group.teeTime}
          </span>
          {startElsewhere && (
            <span className="mt-1 inline-flex items-center rounded font-bold uppercase" style={{ fontSize: 11, padding: "1px 6px", border: "2px solid #111", letterSpacing: "0.02em" }}>
              Start hull {group.startHole}
            </span>
          )}
        </div>
      </div>
      <div style={{ height: 2, background: "#111", margin: "8px 0" }} />
      <ul className="flex flex-1 flex-col justify-center" style={{ gap: 6 }}>
        {group.players.map((p, i) => (
          <li key={p.name + i} className="flex items-center gap-2">
            {showTeams && p.teamColor && <span aria-hidden="true" className="shrink-0 rounded-sm" style={{ width: 12, height: 22, background: p.teamColor }} />}
            <div className="min-w-0 flex-1">
              <p className="truncate font-bold leading-tight" style={{ fontSize: 19 }}>
                {p.name}
              </p>
              {(showTeams || showClass) && (
                <p className="truncate font-medium leading-tight text-neutral-500" style={{ fontSize: 12 }}>
                  {[showTeams && p.teamName, showClass && p.className && `Klasse ${p.className}`].filter(Boolean).join(" · ")}
                </p>
              )}
            </div>
            {showHcp && (
              <span className="shrink-0 rounded font-bold tabular-nums" style={{ fontSize: 14, padding: "1px 7px", background: "#f3f4f6", border: "1px solid #d1d5db" }}>
                {p.hcp}
              </span>
            )}
          </li>
        ))}
      </ul>
    </div>
  )
}

function chunk<T>(arr: T[], size: number): T[][] {
  const out: T[][] = []
  for (let i = 0; i < arr.length; i += size) out.push(arr.slice(i, i + size))
  return out
}

export function PrintCartTags({
  organizationId,
  tournamentId,
  roundId,
  sessionId,
  initialPaper = "a4",
  initialOrientation = "portrait",
}: {
  organizationId: string
  tournamentId: string
  roundId?: string
  sessionId?: string
  initialPaper?: PaperSize
  initialOrientation?: Orientation
}) {
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [tournamentName, setTournamentName] = useState("Turnering")
  const [groups, setGroups] = useState<TagGroup[]>([])
  const [isCup, setIsCup] = useState(false)

  const [paper, setPaper] = useState<PaperSize>(initialPaper)
  const [orientation, setOrientation] = useState<Orientation>(initialOrientation)
  const [showHcp, setShowHcp] = useState(true)
  const [showStartHole, setShowStartHole] = useState(true)
  const [showClass, setShowClass] = useState(false)
  const [showTeams, setShowTeams] = useState(true)
  const [showHeader, setShowHeader] = useState(true)
  const [downloading, setDownloading] = useState(false)

  useEffect(() => {
    let cancelled = false
    async function load() {
      setLoading(true)
      setError(null)
      try {
        const t = await fetchTournament(organizationId, tournamentId)
        if (cancelled) return
        setTournamentName(t?.name ?? "Turnering")

        if (roundId) {
          const [rounds, groupsRes, roundParticipants, tournamentParticipants] = await Promise.all([
            fetchRounds(organizationId, tournamentId),
            fetchRoundGroups(organizationId, tournamentId, roundId),
            fetchRoundParticipants(organizationId, tournamentId, roundId),
            fetchTournamentParticipants(organizationId, tournamentId),
          ])
          const r = rounds.find((x: ApiRound) => x.id === roundId) ?? null
          if (!r) throw new Error("Fant ikke runden.")
          const rpById = new Map<string, ApiRoundParticipant>(roundParticipants.map((rp) => [rp.id, rp]))
          const tpById = new Map<string, ApiTournamentParticipant>(tournamentParticipants.map((tp) => [tp.id, tp]))

          const built: TagGroup[] = groupsRes.groups.map((g, i) => ({
            cart: g.sequence ?? i + 1,
            teeTime: r.start_mode === "shotgun" ? "Shotgun" : g.tee_time ? new Date(g.tee_time).toLocaleTimeString("no-NO", { hour: "2-digit", minute: "2-digit" }) : "–",
            startHole: g.start_hole ?? r.start_hole,
            players: g.participants.map((gp) => {
              const rp = rpById.get(gp.round_participant_id)
              const tp = rp ? tpById.get(rp.tournament_participant_id) : undefined
              return {
                name: gp.player_name,
                hcp: tp?.handicap_index_snapshot != null ? tp.handicap_index_snapshot.toFixed(1).replace(".", ",") : "–",
                className: tp?.class_name ?? "",
              }
            }),
          }))
          if (cancelled) return
          setIsCup(false)
          setGroups(built)
        } else if (sessionId) {
          const [sessions, matches, teams] = await Promise.all([
            fetchSessions(organizationId, tournamentId),
            fetchMatches(organizationId, sessionId),
            fetchTeams(organizationId, tournamentId),
          ])
          const s = sessions.find((x: ApiSession) => x.id === sessionId) ?? null
          if (!s) throw new Error("Fant ikke økten.")
          const teamById = new Map<string, ApiTeam>(teams.map((tm) => [tm.id, tm]))

          const built: TagGroup[] = matches.map((m: ApiMatch) => ({
            cart: m.sequence,
            teeTime: s.start_mode === "shotgun" ? "Shotgun" : m.tee_time ? new Date(m.tee_time).toLocaleTimeString("no-NO", { hour: "2-digit", minute: "2-digit" }) : "–",
            startHole: m.start_hole ?? s.start_hole,
            players: m.participants.map((mp) => {
              const team = teamById.get(mp.team_side === "a" ? m.team_a_id : m.team_b_id)
              return {
                name: mp.player_name,
                hcp: mp.playing_handicap != null ? String(mp.playing_handicap) : "–",
                className: "",
                teamName: team?.name,
                teamColor: team?.color ?? undefined,
              }
            }),
          }))
          if (cancelled) return
          setIsCup(true)
          setGroups(built)
        } else {
          throw new Error("Mangler runde- eller økt-ID.")
        }
      } catch {
        if (!cancelled) setError("Klarte ikke å laste data for cart-tagsene. Prøv igjen.")
      } finally {
        if (!cancelled) setLoading(false)
      }
    }
    void load()
    return () => {
      cancelled = true
    }
  }, [organizationId, tournamentId, roundId, sessionId])

  const sheetMm = useMemo(() => {
    const base = PAPER_MM[paper]
    return orientation === "portrait" ? { w: base.w, h: base.h } : { w: base.h, h: base.w }
  }, [paper, orientation])
  const grid = orientation === "portrait" ? { cols: 2, rows: 3 } : { cols: 3, rows: 2 }
  const perSheet = grid.cols * grid.rows

  const frameRef = useRef<HTMLDivElement>(null)
  const [scale, setScale] = useState(1)
  useEffect(() => {
    const el = frameRef.current
    if (!el) return
    const compute = () => {
      const avail = el.clientWidth - 32
      const target = sheetMm.w * PX_PER_MM
      setScale(Math.min(1, avail / target))
    }
    compute()
    const ro = new ResizeObserver(compute)
    ro.observe(el)
    return () => ro.disconnect()
  }, [sheetMm.w])

  const sheetStyle: CSSProperties = { width: sheetMm.w * PX_PER_MM, height: sheetMm.h * PX_PER_MM, transform: `scale(${scale})`, transformOrigin: "top center" }
  const pages = chunk(groups, perSheet)

  async function downloadPdf() {
    setDownloading(true)
    try {
      const res = await fetch(`/orgs/${organizationId}/print/pdf`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        credentials: "include",
        body: JSON.stringify({
          kind: "cart-tags",
          tournament_id: tournamentId,
          round_id: roundId ?? null,
          session_id: sessionId ?? null,
          paper: paper === "a4" ? "A4" : "Letter",
          orientation,
        }),
      })
      if (!res.ok) throw new Error()
      const blob = await res.blob()
      const url = URL.createObjectURL(blob)
      const a = document.createElement("a")
      a.href = url
      a.download = "teecup-cart-tags.pdf"
      document.body.appendChild(a)
      a.click()
      a.remove()
      URL.revokeObjectURL(url)
    } catch {
      setError("Klarte ikke å generere PDF-en. Prøv igjen.")
    } finally {
      setDownloading(false)
    }
  }

  const ready = !loading

  return (
    <div className="min-h-dvh bg-background text-foreground" data-print-ready={ready ? "true" : undefined}>
      <style>{`@page { size: ${PAPER_MM[paper].label} ${orientation}; margin: 8mm; }`}</style>

      <div className="mx-auto flex max-w-7xl flex-col gap-6 p-4 lg:flex-row lg:p-6 print:block print:p-0">
        <aside className="lg:w-80 lg:shrink-0 print:hidden">
          <div className="flex flex-col gap-6 rounded-2xl border border-border bg-card p-5 lg:sticky lg:top-6">
            <div className="flex flex-col gap-1">
              <h1 className="flex items-center gap-2 text-lg font-extrabold">
                <Printer aria-hidden="true" className="size-5 text-primary" />
                Skriv ut cart-tags
              </h1>
              <p className="text-sm leading-relaxed text-muted-foreground text-pretty">Flere tags per ark. Klipp langs de stiplede linjene etter utskrift.</p>
            </div>

            {error ? <p className="text-sm font-medium text-destructive">{error}</p> : null}

            <Field label="Papirstørrelse">
              <Segmented ariaLabel="Papirstørrelse" value={paper} onChange={(v) => setPaper(v as PaperSize)} options={[{ value: "a4", label: "A4" }, { value: "letter", label: "Letter" }]} />
            </Field>
            <Field label="Retning" hint="Styrer hvordan tag-ene plasseres på arket.">
              <Segmented ariaLabel="Retning" value={orientation} onChange={(v) => setOrientation(v as Orientation)} options={[{ value: "portrait", label: "Portrett" }, { value: "landscape", label: "Landskap" }]} />
            </Field>

            <div className="flex flex-col gap-1">
              <p className="text-xs font-bold uppercase tracking-wide text-muted-foreground">Valgfrie felt</p>
              <div className="flex flex-col divide-y divide-border">
                <Toggle label="HCP per spiller" checked={showHcp} onChange={setShowHcp} />
                <Toggle label="Starthull" hint="Vises kun når gruppen ikke starter på hull 1." checked={showStartHole} onChange={setShowStartHole} />
                <Toggle label="Klasse per spiller" checked={showClass} onChange={setShowClass} disabled={isCup} />
                <Toggle label="Lagnavn + farge" hint={isCup ? undefined : "Kun for Cup-format."} checked={showTeams} onChange={setShowTeams} disabled={!isCup} />
                <Toggle label="Turneringsnavn på hver tag" checked={showHeader} onChange={setShowHeader} />
              </div>
            </div>

            <button
              type="button"
              onClick={downloadPdf}
              disabled={downloading || loading || groups.length === 0}
              className="flex h-11 w-full items-center justify-center gap-2 rounded-xl bg-primary px-4 font-bold text-primary-foreground shadow-sm transition-colors hover:bg-primary/90 disabled:opacity-60"
            >
              <Download aria-hidden="true" className="size-4" />
              {downloading ? "Genererer …" : "Last ned PDF"}
            </button>
            <p className="-mt-3 text-center text-xs text-muted-foreground">{groups.length > 0 ? `${groups.length} tags, ${pages.length} ark.` : loading ? "Laster …" : "Ingen data ennå."}</p>
          </div>
        </aside>

        <main className="min-w-0 flex-1 print:w-full">
          <div ref={frameRef} className="flex flex-col items-center gap-6 rounded-2xl bg-muted/40 p-4 print:gap-0 print:rounded-none print:bg-transparent print:p-0">
            {loading ? (
              <p className="p-8 text-sm text-muted-foreground">Laster cart-tags …</p>
            ) : pages.length === 0 ? (
              <p className="p-8 text-sm text-muted-foreground">Ingen grupper eller matcher funnet ennå.</p>
            ) : (
              pages.map((pageGroups, pageIndex) => (
                <div key={pageIndex} style={{ height: sheetMm.h * PX_PER_MM * scale }} className="print:h-auto print:break-after-page">
                  <div style={sheetStyle} className="flex flex-col overflow-hidden bg-white text-neutral-900 shadow-lg ring-1 ring-black/10 print:!scale-100 print:shadow-none print:ring-0">
                    <div
                      className="grid flex-1"
                      style={{ padding: 10 * PX_PER_MM, gap: 0, gridTemplateColumns: `repeat(${grid.cols}, 1fr)`, gridTemplateRows: `repeat(${grid.rows}, 1fr)` }}
                    >
                      {pageGroups.map((group, i) => {
                        const col = i % grid.cols
                        const row = Math.floor(i / grid.cols)
                        return (
                          <div
                            key={group.cart}
                            className="relative"
                            style={{
                              borderRight: col < grid.cols - 1 ? "1.5px dashed #9ca3af" : undefined,
                              borderBottom: row < grid.rows - 1 ? "1.5px dashed #9ca3af" : undefined,
                            }}
                          >
                            {col < grid.cols - 1 && (
                              <Scissors aria-hidden="true" className="absolute top-1/2 -translate-y-1/2 text-neutral-400" style={{ right: -8, width: 14, height: 14, background: "white" }} />
                            )}
                            {row < grid.rows - 1 && (
                              <Scissors aria-hidden="true" className="absolute left-1/2 -translate-x-1/2 rotate-90 text-neutral-400" style={{ bottom: -8, width: 14, height: 14, background: "white" }} />
                            )}
                            <CartTag group={group} tournamentName={tournamentName} showHcp={showHcp} showStartHole={showStartHole} showClass={showClass} showTeams={showTeams} showHeader={showHeader} />
                          </div>
                        )
                      })}
                    </div>
                  </div>
                </div>
              ))
            )}
          </div>
        </main>
      </div>
    </div>
  )
}
