"use client"

// Utslagsgrupper (2026-08-18) -- hvem spiller med hvem, klokka når, for
// én runde i en individuell turnering. Bruker: "Jeg må jo kunne
// bulksjekke hvem som skal spille fra hvor, med hvem, klokka når?"
// Design bekreftet: TRADISJONELT utslag (samme starthull for alle,
// rundens eget start_hole -- uendret her), staggerte klokkeslett per
// gruppe med fast intervall, MANUELL gruppesammensetning med et forslag
// å justere, FAST gruppestørrelse.
//
// Håndkodet direkte (ikke sendt via V0 først) -- bruker ba eksplisitt om
// funksjonen NÅ ("Jeg vil ha den nå, takk"), samme avveining som
// DuplicateStep i player-import-panel.tsx: en avgrenset, funksjonell
// arbeidsflate satt inn i en eksisterende flyt, bygget med de samme
// globale design-tokenene som resten av appen (border/bg-card/bg-primær
// osv.), ikke en forsøkt "ferdig polert" ny flaggskip-skjerm. Kan
// poleres videre via V0 senere om ønskelig.

import { useEffect, useState } from "react"
import { Clock, Plus, Trash2, X } from "lucide-react"
import { cn } from "@/lib/utils"

type ApiGroupParticipant = {
  round_participant_id: string
  player_name: string
}

type ApiRoundGroup = {
  id: string | null
  sequence: number
  tee_time: string | null
  tee_time_override: string | null
  participants: ApiGroupParticipant[]
}

type ApiRoundGroups = {
  groups: ApiRoundGroup[]
  ungrouped: ApiGroupParticipant[]
}

type ApiRoundInfo = {
  scheduled_at: string | null
  tee_interval_minutes: number | null
  start_hole: number
}

function formatTeeTime(iso: string | null) {
  if (!iso) return null
  const date = new Date(iso)
  if (Number.isNaN(date.getTime())) return null
  return date.toLocaleTimeString("no-NO", { hour: "2-digit", minute: "2-digit" })
}

// datetime-local-inputet gir "YYYY-MM-DDTHH:mm" (ingen tidssone) -- server
// (Pydantic datetime-felt) godtar dette direkte, tolkes som lokal tid.
function toDatetimeLocalValue(iso: string | null) {
  if (!iso) return ""
  const date = new Date(iso)
  if (Number.isNaN(date.getTime())) return ""
  const pad = (n: number) => String(n).padStart(2, "0")
  return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(date.getHours())}:${pad(date.getMinutes())}`
}

const CONTROL =
  "h-10 rounded-lg border border-border bg-background px-3 text-sm font-semibold text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"

export function RoundGroupsPanel({
  base,
  roundId,
  roundLabel,
  onClose,
}: {
  base: string
  roundId: string
  roundLabel: string
  onClose: () => void
}) {
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [saving, setSaving] = useState(false)
  const [savedMessage, setSavedMessage] = useState<string | null>(null)

  const [roundInfo, setRoundInfo] = useState<ApiRoundInfo | null>(null)
  const [scheduledAtInput, setScheduledAtInput] = useState("")
  const [intervalInput, setIntervalInput] = useState("")

  const [groups, setGroups] = useState<ApiRoundGroup[]>([])
  const [ungrouped, setUngrouped] = useState<ApiGroupParticipant[]>([])
  const [groupSize, setGroupSize] = useState("4")

  async function loadAll() {
    setLoading(true)
    setError(null)
    try {
      const [roundRes, groupsRes] = await Promise.all([
        fetch(`${base}/rounds`, { credentials: "include" }),
        fetch(`${base}/rounds/${roundId}/groups`, { credentials: "include" }),
      ])
      if (!roundRes.ok || !groupsRes.ok) throw new Error()
      const rounds: (ApiRoundInfo & { id: string })[] = await roundRes.json()
      const thisRound = rounds.find((r) => r.id === roundId) ?? null
      const groupsData: ApiRoundGroups = await groupsRes.json()
      setRoundInfo(thisRound)
      setScheduledAtInput(toDatetimeLocalValue(thisRound?.scheduled_at ?? null))
      setIntervalInput(thisRound?.tee_interval_minutes?.toString() ?? "")
      setGroups(groupsData.groups)
      setUngrouped(groupsData.ungrouped)
    } catch {
      setError("Klarte ikke å laste utslagsgruppene. Prøv igjen.")
    } finally {
      setLoading(false)
    }
  }

  useEffect(() => {
    void loadAll()
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [roundId])

  async function saveSchedule() {
    setError(null)
    // <input type="datetime-local"> gir en TIDSSONELØS streng som betyr
    // "organisatorens lokale klokkeslett" (f.eks. "10:00" i Norge). new
    // Date(...) på en slik streng tolkes av nettleseren som LOKAL tid --
    // .toISOString() konverterer deretter til riktig UTC-tidspunkt FØR
    // sending. Uten dette steget ville "10:00" blitt lagret som 10:00 UTC
    // (feil med hele tidssoneavviket, f.eks. 2 timer for norsk sommertid)
    // -- funnet under egen scratch-verifisering av akkurat denne skjermen.
    const scheduledAtIso = scheduledAtInput ? new Date(scheduledAtInput).toISOString() : null
    const res = await fetch(`${base}/rounds/${roundId}`, {
      method: "PATCH",
      headers: { "Content-Type": "application/json" },
      credentials: "include",
      body: JSON.stringify({
        scheduled_at: scheduledAtIso,
        tee_interval_minutes: intervalInput.trim() ? Number(intervalInput) : null,
      }),
    })
    if (!res.ok) {
      setError("Klarte ikke å lagre utslagstidspunktet.")
      return
    }
    await loadAll()
  }

  async function suggest() {
    const size = Number(groupSize)
    if (!size || size < 1) return
    const hasExistingWork = groups.some((g) => g.participants.length > 0)
    if (hasExistingWork && !confirm("Dette erstatter det du eventuelt allerede har justert her (ikke lagret ennå). Fortsette?")) {
      return
    }
    setError(null)
    const res = await fetch(`${base}/rounds/${roundId}/groups/suggest`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      credentials: "include",
      body: JSON.stringify({ group_size: size }),
    })
    if (!res.ok) {
      setError("Klarte ikke å beregne et forslag.")
      return
    }
    const data: ApiRoundGroups = await res.json()
    setGroups(data.groups)
    setUngrouped(data.ungrouped)
    setSavedMessage(null)
  }

  function addEmptyGroup() {
    const nextSequence = (groups.reduce((m, g) => Math.max(m, g.sequence), 0) || 0) + 1
    setGroups((prev) => [...prev, { id: null, sequence: nextSequence, tee_time: null, tee_time_override: null, participants: [] }])
  }

  function removeGroup(sequence: number) {
    const group = groups.find((g) => g.sequence === sequence)
    if (!group) return
    setUngrouped((prev) => [...prev, ...group.participants])
    setGroups((prev) => prev.filter((g) => g.sequence !== sequence))
  }

  // VIKTIG: `moved` må leses SYNKRONT fra det gjeldende (allerede rendrede)
  // state-et, IKKE inne i en setState-oppdateringsfunksjon -- React kjører
  // ikke oppdateringsfunksjoner umiddelbart, så en `let moved` satt inni én
  // slik funksjon er fortsatt `null` når den leses rett etterpå i samme
  // kall. Funnet under egen scratch-verifisering: en flyttet spiller
  // forsvant sporløst (fjernet fra den gamle gruppen, aldri lagt til den
  // nye) fordi nettopp dette skjedde.
  function moveParticipant(participantId: string, toSequence: number | "ungrouped") {
    const moved =
      groups.flatMap((g) => g.participants).find((p) => p.round_participant_id === participantId) ??
      ungrouped.find((p) => p.round_participant_id === participantId)
    if (!moved) return

    setGroups((prev) =>
      prev.map((g) => {
        if (g.sequence === toSequence) {
          const withoutMoved = g.participants.filter((p) => p.round_participant_id !== participantId)
          return { ...g, participants: [...withoutMoved, moved] }
        }
        return { ...g, participants: g.participants.filter((p) => p.round_participant_id !== participantId) }
      }),
    )
    setUngrouped((prev) => {
      const withoutMoved = prev.filter((p) => p.round_participant_id !== participantId)
      return toSequence === "ungrouped" ? [...withoutMoved, moved] : withoutMoved
    })
  }

  async function save() {
    setSaving(true)
    setError(null)
    setSavedMessage(null)
    try {
      const res = await fetch(`${base}/rounds/${roundId}/groups`, {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        credentials: "include",
        body: JSON.stringify({
          groups: groups.map((g) => ({
            sequence: g.sequence,
            tee_time_override: null,
            round_participant_ids: g.participants.map((p) => p.round_participant_id),
          })),
        }),
      })
      if (!res.ok) throw new Error()
      const data: ApiRoundGroups = await res.json()
      setGroups(data.groups)
      setUngrouped(data.ungrouped)
      setSavedMessage("Lagret.")
    } catch {
      setError("Klarte ikke å lagre utslagsgruppene. Prøv igjen.")
    } finally {
      setSaving(false)
    }
  }

  const allSequences = groups.map((g) => g.sequence).sort((a, b) => a - b)

  function GroupSelect({ participantId, currentSequence }: { participantId: string; currentSequence: number | "ungrouped" }) {
    return (
      <label className="flex items-center gap-2">
        <span className="sr-only">Gruppe</span>
        <select
          value={currentSequence}
          onChange={(e) => {
            const v = e.target.value
            moveParticipant(participantId, v === "ungrouped" ? "ungrouped" : Number(v))
          }}
          className={cn(CONTROL, "h-9 px-2 text-xs")}
        >
          <option value="ungrouped">Ugruppert</option>
          {allSequences.map((seq) => (
            <option key={seq} value={seq}>
              Gruppe {seq}
            </option>
          ))}
        </select>
      </label>
    )
  }

  return (
    <div className="fixed inset-0 z-50 flex flex-col overflow-y-auto bg-background">
      <div className="sticky top-0 z-10 flex items-center justify-between gap-3 border-b border-border bg-background px-5 py-4 sm:px-8">
        <div className="flex flex-col">
          <h1 className="text-lg font-black text-foreground">Utslagsgrupper</h1>
          <p className="text-sm font-semibold text-muted-foreground">{roundLabel}</p>
        </div>
        <button
          type="button"
          onClick={onClose}
          aria-label="Lukk"
          className="inline-flex size-11 items-center justify-center rounded-xl border border-border bg-card text-foreground transition-colors hover:bg-accent/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
        >
          <X aria-hidden="true" className="size-5" />
        </button>
      </div>

      <div className="mx-auto flex w-full max-w-5xl flex-col gap-6 px-5 py-6 sm:px-8">
        {error && (
          <div className="rounded-2xl border border-destructive/30 bg-destructive/5 px-4 py-3 text-sm font-medium text-destructive">
            {error}
          </div>
        )}

        {loading ? (
          <p className="text-sm font-medium text-muted-foreground">Laster…</p>
        ) : (
          <>
            <section className="flex flex-col gap-3 rounded-2xl border border-border bg-card p-4 shadow-md shadow-black/8 sm:p-5">
              <h2 className="text-base font-bold text-foreground">Første utslag og intervall</h2>
              <p className="text-sm leading-relaxed text-muted-foreground text-pretty">
                Alle grupper starter fra samme hull (hull {roundInfo?.start_hole ?? 1}, satt for hele runden),
                med staggerte klokkeslett ut fra intervallet under. Gruppe 1 slår ut først, gruppe 2 dette
                antall minutter senere, og så videre.
              </p>
              <div className="flex flex-col gap-3 sm:flex-row sm:items-end sm:gap-4">
                <label className="flex flex-1 flex-col gap-1.5">
                  <span className="text-sm font-bold text-foreground">Første utslag</span>
                  <input
                    type="datetime-local"
                    value={scheduledAtInput}
                    onChange={(e) => setScheduledAtInput(e.target.value)}
                    className={CONTROL}
                  />
                </label>
                <label className="flex flex-1 flex-col gap-1.5">
                  <span className="text-sm font-bold text-foreground">Intervall (minutter)</span>
                  <input
                    type="number"
                    min={1}
                    value={intervalInput}
                    onChange={(e) => setIntervalInput(e.target.value)}
                    placeholder="f.eks. 10"
                    className={CONTROL}
                  />
                </label>
                <button
                  type="button"
                  onClick={() => void saveSchedule()}
                  className="inline-flex h-10 shrink-0 items-center justify-center rounded-xl border border-border bg-background px-5 text-sm font-bold text-foreground transition-colors hover:bg-accent/50"
                >
                  Lagre tidspunkt
                </button>
              </div>
            </section>

            <section className="flex flex-col gap-3 rounded-2xl border border-border bg-card p-4 shadow-md shadow-black/8 sm:p-5">
              <div className="flex flex-wrap items-end justify-between gap-3">
                <div className="flex flex-col gap-1">
                  <h2 className="text-base font-bold text-foreground">Grupper</h2>
                  <p className="text-sm text-muted-foreground">
                    Foreslå en fordeling, juster hvem som spiller sammen, lagre når du er fornøyd.
                  </p>
                </div>
                <div className="flex items-end gap-2">
                  <label className="flex flex-col gap-1.5">
                    <span className="text-xs font-bold text-foreground">Gruppestørrelse</span>
                    <input
                      type="number"
                      min={1}
                      max={12}
                      value={groupSize}
                      onChange={(e) => setGroupSize(e.target.value)}
                      className={cn(CONTROL, "w-20")}
                    />
                  </label>
                  <button
                    type="button"
                    onClick={() => void suggest()}
                    className="inline-flex h-10 items-center justify-center rounded-xl border border-border bg-background px-4 text-sm font-bold text-foreground transition-colors hover:bg-accent/50"
                  >
                    Foreslå grupper
                  </button>
                </div>
              </div>

              <div className="flex flex-col gap-3">
                {groups.length === 0 && (
                  <p className="text-sm font-medium text-muted-foreground">
                    Ingen grupper ennå -- bruk "Foreslå grupper" eller "Ny gruppe".
                  </p>
                )}
                {groups
                  .slice()
                  .sort((a, b) => a.sequence - b.sequence)
                  .map((g) => (
                    <div key={g.sequence} className="rounded-xl border border-border bg-background p-3 sm:p-4">
                      <div className="mb-2 flex items-center justify-between gap-2">
                        <div className="flex items-center gap-2">
                          <span className="flex size-8 items-center justify-center rounded-full bg-info/15 text-sm font-extrabold tabular-nums text-info">
                            {g.sequence}
                          </span>
                          <span className="inline-flex items-center gap-1.5 text-sm font-bold text-foreground">
                            <Clock aria-hidden="true" className="size-4 text-muted-foreground" />
                            {formatTeeTime(g.tee_time) ?? "Ingen klokkeslett satt"}
                          </span>
                        </div>
                        <button
                          type="button"
                          onClick={() => removeGroup(g.sequence)}
                          aria-label={`Fjern gruppe ${g.sequence}`}
                          className="inline-flex size-8 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:bg-destructive/10 hover:text-destructive"
                        >
                          <Trash2 aria-hidden="true" className="size-4" />
                        </button>
                      </div>
                      {g.participants.length === 0 ? (
                        <p className="text-xs font-medium text-muted-foreground">Ingen spillere i denne gruppen ennå.</p>
                      ) : (
                        <ul className="flex flex-col gap-2">
                          {g.participants.map((p) => (
                            <li key={p.round_participant_id} className="flex items-center justify-between gap-2">
                              <span className="truncate text-sm font-semibold text-foreground">{p.player_name}</span>
                              <GroupSelect participantId={p.round_participant_id} currentSequence={g.sequence} />
                            </li>
                          ))}
                        </ul>
                      )}
                    </div>
                  ))}
                <button
                  type="button"
                  onClick={addEmptyGroup}
                  className="inline-flex h-10 items-center justify-center gap-2 rounded-xl border border-dashed border-border text-sm font-bold text-muted-foreground transition-colors hover:border-primary/50 hover:text-foreground"
                >
                  <Plus aria-hidden="true" className="size-4" />
                  Ny gruppe
                </button>
              </div>

              <div className="border-t border-border pt-3">
                <h3 className="mb-2 text-sm font-bold text-foreground">
                  Ugrupperte ({ungrouped.length})
                </h3>
                {ungrouped.length === 0 ? (
                  <p className="text-xs font-medium text-muted-foreground">Alle deltakere er i en gruppe.</p>
                ) : (
                  <ul className="flex flex-col gap-2">
                    {ungrouped.map((p) => (
                      <li key={p.round_participant_id} className="flex items-center justify-between gap-2 rounded-lg border border-border px-3 py-2">
                        <span className="truncate text-sm font-semibold text-foreground">{p.player_name}</span>
                        {allSequences.length > 0 ? (
                          <GroupSelect participantId={p.round_participant_id} currentSequence="ungrouped" />
                        ) : (
                          <span className="text-xs text-muted-foreground">Opprett en gruppe først</span>
                        )}
                      </li>
                    ))}
                  </ul>
                )}
              </div>
            </section>

            <div className="flex items-center justify-end gap-3 pb-6">
              {savedMessage && <span className="text-sm font-bold text-tee-strong">{savedMessage}</span>}
              <button
                type="button"
                onClick={() => void save()}
                disabled={saving}
                className="inline-flex h-12 items-center justify-center rounded-xl bg-primary px-6 text-sm font-bold text-primary-foreground shadow-sm transition-colors hover:bg-primary/90 disabled:cursor-not-allowed disabled:opacity-50"
              >
                {saving ? "Lagrer..." : "Lagre utslagsgrupper"}
              </button>
            </div>
          </>
        )}
      </div>
    </div>
  )
}
