"use client"

// Rediger HELE organisasjonens spillerpool, når som helst -- ikke bare de
// spillerne som tilfeldigvis dukker opp i en turnerings deltakerliste
// (2026-08-18, "lettere krise": brukeren kunne ikke redigere spillere i
// org-turneringer, ba eksplisitt om at tabellen fra spillerimporten (ADR-082)
// skal være tilgjengelig for redigering til enhver tid, ikke bare under en
// fersk CSV-import).
//
// Gjenbruker `PlayerImportView` (V0-eksportert, se player-import-view.tsx)
// UENDRET som selve tabell-UI-et via en ny `mode.kind === "roster"` --
// ORKESTRERINGEN her er ny og annerledes enn player-import-panel.tsx sin:
// radene starter FYLT UT fra `GET /orgs/{id}/players` (ikke en opplastet
// CSV), og "Lagre" gjør ekte PATCH-per-endret-felt mot eksisterende
// spillere (IKKE `/players/bulk`, som kun fyller TOMME felt og aldri
// overskriver et allerede satt navn/verdi -- feil oppførsel for en ekte
// "rett dette feltet"-redigeringsskjerm, se app/routers/players.py sin
// egen COALESCE-forklaring). Nye rader (lagt til i tabellen, uten kjent
// spiller-id) opprettes med vanlig POST, én om gangen.

import { useEffect, useState } from "react"
import { PlayerImportView, type DraftRow, type FieldKey } from "@/components/player-import-view"

const EMPTY_ROW: Omit<DraftRow, "key"> = {
  display_name: "",
  email: "",
  handicap_index: "",
  gender: "",
  birth_date: "",
  mobile: "",
  club: "",
  nickname: "",
  country: "",
  club_member_number: "",
  first_name: "",
  last_name: "",
  comment: "",
  team_name: "",
  class_name: "",
}

// Speiler player-import-panel.tsx sin gjeng-konvertering, men begge veier
// -- radene her starter fra EKTE backend-data (m/f/x), ikke rå CSV-tekst.
function fromBackendGender(value: string | null): string {
  if (value === "f") return "female"
  if (value === "m") return "male"
  if (value === "x") return "other"
  return ""
}
function toBackendGender(value: string): string | null {
  if (value === "female") return "f"
  if (value === "male") return "m"
  if (value === "other") return "x"
  return null
}

type ApiPlayer = {
  id: string
  display_name: string
  handicap_index: number | null
  gender: string | null
  mobile: string | null
  email: string | null
  birth_date: string | null
  nickname: string | null
  country: string | null
  club: string | null
  club_member_number: string | null
  first_name: string | null
  last_name: string | null
  paid: boolean
  comment: string | null
}

// De feltene et rad-objekt kan avvike fra originalen på -- team_name/
// class_name finnes ikke i roster-modus (ingen turneringskontekst), og
// display_name/email/gender/birth_date/handicap_index håndteres med egen
// konvertering ved diff, ikke rå strenglikhet.
const PLAYER_FIELDS: FieldKey[] = [
  "display_name",
  "email",
  "handicap_index",
  "gender",
  "birth_date",
  "mobile",
  "club",
  "nickname",
  "country",
  "club_member_number",
  "first_name",
  "last_name",
  "comment",
]

function playerToRow(p: ApiPlayer): DraftRow {
  return {
    key: p.id,
    ...EMPTY_ROW,
    display_name: p.display_name,
    email: p.email ?? "",
    handicap_index: p.handicap_index !== null ? String(p.handicap_index) : "",
    gender: fromBackendGender(p.gender),
    birth_date: p.birth_date ?? "",
    mobile: p.mobile ?? "",
    club: p.club ?? "",
    nickname: p.nickname ?? "",
    country: p.country ?? "",
    club_member_number: p.club_member_number ?? "",
    first_name: p.first_name ?? "",
    last_name: p.last_name ?? "",
    comment: p.comment ?? "",
  }
}

export function OrgPlayerRosterPanel({
  organizationId,
  onClose,
}: {
  organizationId: string
  onClose: () => void
}) {
  const [step, setStep] = useState<"loading" | "edit" | "saving" | "done">("loading")
  const [rows, setRows] = useState<DraftRow[]>([])
  // Nøkkelen for en rad som ALLEREDE var en ekte spiller er selve
  // spiller-id-en (satt i playerToRow over) -- originalById lar handleSave
  // vite hvilke felt som faktisk endret seg, slik at PATCH-en kun sender
  // det som er rørt (samme prinsipp som backend sin `exclude_unset`).
  const [originalById, setOriginalById] = useState<Record<string, DraftRow>>({})
  const [error, setError] = useState<string | null>(null)
  const [saveWarnings, setSaveWarnings] = useState<string[]>([])

  useEffect(() => {
    let cancelled = false
    fetch(`/orgs/${organizationId}/players`, { credentials: "include" })
      .then((res) => (res.ok ? res.json() : Promise.reject(new Error(`players: ${res.status}`))))
      .then((players: ApiPlayer[]) => {
        if (cancelled) return
        const mapped = players.map(playerToRow)
        setRows(mapped)
        setOriginalById(Object.fromEntries(mapped.map((r) => [r.key, r])))
        setStep("edit")
      })
      .catch(() => {
        if (!cancelled) setError("Klarte ikke å hente spillerne. Prøv å laste siden på nytt.")
      })
    return () => {
      cancelled = true
    }
  }, [organizationId])

  function updateCell(key: string, field: FieldKey, value: string) {
    setRows((prev) => prev.map((r) => (r.key === key ? { ...r, [field]: value } : r)))
  }

  function addBlankRow() {
    setRows((prev) => [...prev, { key: `new-${Date.now()}`, ...EMPTY_ROW }])
  }

  function removeRow(key: string) {
    // Fjerner KUN raden fra denne redigeringsøkten -- sletter ikke
    // spilleren (ingen slette-endepunkt finnes ennå, se kommentar i
    // player-import-view.tsx sin EditTable-beskrivelse for roster-modus).
    setRows((prev) => prev.filter((r) => r.key !== key))
  }

  async function handleSave() {
    setStep("saving")
    setError(null)
    setSaveWarnings([])
    const warnings: string[] = []
    try {
      for (const row of rows) {
        const isExisting = row.key in originalById
        if (isExisting) {
          const original = originalById[row.key]
          const patch: Record<string, unknown> = {}
          for (const field of PLAYER_FIELDS) {
            if (row[field] === original[field]) continue
            if (field === "gender") {
              patch.gender = toBackendGender(row.gender)
            } else if (field === "handicap_index") {
              patch.handicap_index = row.handicap_index.trim() ? Number(row.handicap_index) : null
            } else if (field === "birth_date") {
              patch.birth_date = row.birth_date.trim() || null
            } else {
              patch[field] = row[field].trim() || null
            }
          }
          // display_name er required (min_length=1) på backend -- aldri
          // send en tom streng, selv om raden ble tømt ved et uhell.
          if ("display_name" in patch && !String(patch.display_name ?? "").trim()) {
            delete patch.display_name
          }
          if (Object.keys(patch).length === 0) continue
          const res = await fetch(`/orgs/${organizationId}/players/${row.key}`, {
            method: "PATCH",
            headers: { "Content-Type": "application/json" },
            credentials: "include",
            body: JSON.stringify(patch),
          })
          if (!res.ok) {
            warnings.push(`${row.display_name || "(uten navn)"}: klarte ikke å lagre endringen.`)
          }
        } else if (row.display_name.trim()) {
          // Ny rad (lagt til i tabellen denne økten) -- ekte oppretting,
          // én om gangen (samme mønster som player-import-panel.tsx).
          const res = await fetch(`/orgs/${organizationId}/players`, {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            credentials: "include",
            body: JSON.stringify({
              display_name: row.display_name.trim(),
              email: row.email.trim() || null,
              handicap_index: row.handicap_index.trim() ? Number(row.handicap_index) : null,
              gender: toBackendGender(row.gender),
              birth_date: row.birth_date.trim() || null,
              mobile: row.mobile.trim() || null,
              club: row.club.trim() || null,
              nickname: row.nickname.trim() || null,
              country: row.country.trim() || null,
              club_member_number: row.club_member_number.trim() || null,
              first_name: row.first_name.trim() || null,
              last_name: row.last_name.trim() || null,
              comment: row.comment.trim() || null,
            }),
          })
          if (!res.ok) {
            warnings.push(`${row.display_name}: klarte ikke å opprette spilleren.`)
          }
        }
      }
      setSaveWarnings(warnings)
      setStep("done")
    } catch {
      setError("Lagringen feilet. Prøv igjen.")
      setStep("edit")
    }
  }

  if (step === "loading") {
    return (
      <div className="fixed inset-0 z-50 flex 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>
    )
  }

  return (
    <PlayerImportView
      mode={{ kind: "roster" }}
      step={step}
      csvHeaders={[]}
      columnMapping={{}}
      rows={rows}
      errorMessage={error}
      saveWarnings={saveWarnings}
      onFileSelected={() => {}}
      onColumnMappingChange={() => {}}
      onConfirmMapping={() => {}}
      onCellChange={updateCell}
      onDeleteRow={removeRow}
      onAddBlankRow={addBlankRow}
      onSave={() => void handleSave()}
      onClose={onClose}
    />
  )
}
