"use client"

// V0-eksportert visning (2026-08-17, "stor skjerm først"-prompt, se
// ARCHITECTURE_DECISIONS.md ADR-082) -- ren kontrollert visning, ingen
// egne API-kall. All logikk (CSV-parsing/kolonnegjetting/lagre-
// orkestrering) bor i player-import-panel.tsx, som importerer OG
// wrapper denne. IKKE endre denne filen for å tilpasse den til
// backend-detaljer (f.eks. kjønn-verdier) -- oversett i orkestrerings-
// laget i stedet, se player-import-panel.tsx sin handleSave.

import type React from "react"
import { useRef } from "react"
import {
  AlertCircle,
  CheckCircle2,
  FileUp,
  Plus,
  Trash2,
  TriangleAlert,
  UploadCloud,
  X,
} from "lucide-react"
import { cn } from "@/lib/utils"

export type FieldKey =
  | "display_name"
  | "email"
  | "handicap_index"
  | "gender"
  | "birth_date"
  | "mobile"
  | "club"
  | "nickname"
  | "country"
  | "club_member_number"
  | "first_name"
  | "last_name"
  | "comment"
  | "team_name"
  | "class_name"

export type DraftRow = { key: string } & Record<FieldKey, string>

export type Mode =
  | { kind: "team"; teams: { id: string; name: string }[] }
  | { kind: "individual"; classes: { id: string; name: string }[] }
  // Organisasjonens hele spillerpool, utenfor enhver turneringskontekst
  // (2026-08-18, se org-player-roster-panel.tsx) -- ingen lag/klasse-
  // kolonner (de gir ikke mening uten en turnering), og radene starter
  // FYLT UT fra eksisterende spillere i stedet for en opplastet CSV.
  | { kind: "roster" }

export type PlayerImportStep = "upload" | "map" | "edit" | "saving" | "done"

export type PlayerImportViewProps = {
  mode: Mode
  step: PlayerImportStep
  csvHeaders: string[]
  columnMapping: Record<number, FieldKey | "">
  rows: DraftRow[]
  errorMessage: string | null
  saveWarnings: string[]
  onFileSelected: (file: File) => void
  onColumnMappingChange: (columnIndex: number, field: FieldKey | "") => void
  onConfirmMapping: () => void
  onCellChange: (rowKey: string, field: FieldKey, value: string) => void
  onDeleteRow: (rowKey: string) => void
  onAddBlankRow: () => void
  onSave: () => void
  onClose: () => void
}

// Norwegian labels for every field. team_name / class_name are filtered by mode.
const FIELD_LABELS: Record<FieldKey, string> = {
  display_name: "Navn",
  email: "E-post",
  handicap_index: "HCP",
  gender: "Kjønn",
  birth_date: "Fødselsdato",
  mobile: "Mobil",
  club: "Klubb",
  nickname: "Kallenavn",
  country: "Land",
  club_member_number: "Medlemsnr.",
  first_name: "Fornavn",
  last_name: "Etternavn",
  comment: "Kommentar",
  team_name: "Lag",
  class_name: "Klasse",
}

// Field order for the mapping dropdown and edit table columns.
const FIELD_ORDER: FieldKey[] = [
  "display_name",
  "first_name",
  "last_name",
  "nickname",
  "email",
  "mobile",
  "handicap_index",
  "gender",
  "birth_date",
  "club",
  "club_member_number",
  "country",
  "team_name",
  "class_name",
  "comment",
]

// Per-field column width for the edit table. Compact by default so a wide
// screen shows many columns at once; wider for free-text-heavy fields.
const FIELD_MIN_W: Partial<Record<FieldKey, string>> = {
  display_name: "min-w-44",
  first_name: "min-w-36",
  last_name: "min-w-36",
  nickname: "min-w-32",
  email: "min-w-52",
  mobile: "min-w-36",
  handicap_index: "min-w-20",
  gender: "min-w-28",
  birth_date: "min-w-36",
  club: "min-w-44",
  club_member_number: "min-w-28",
  country: "min-w-28",
  team_name: "min-w-40",
  class_name: "min-w-40",
  comment: "min-w-56",
}

const GENDER_OPTIONS: { value: string; label: string }[] = [
  { value: "", label: "—" },
  { value: "female", label: "Kvinne" },
  { value: "male", label: "Mann" },
  { value: "other", label: "Annet" },
]

// Shared control classes. Desktop-first: compact but comfortable (mouse is
// precise) with a clear keyboard focus ring that works in light and dark mode.
const CONTROL_BASE =
  "h-9 rounded-lg border border-border bg-card text-foreground transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background"

const PRIMARY_BTN =
  "inline-flex h-10 items-center justify-center gap-2 rounded-lg bg-primary px-5 font-bold text-primary-foreground shadow-sm transition-colors hover:bg-primary/90 active:scale-[0.98] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50"

const SECONDARY_BTN =
  "inline-flex h-10 items-center justify-center gap-2 rounded-lg border border-border bg-card px-4 font-bold text-foreground transition-colors hover:border-primary/50 hover:bg-accent/40 active:scale-[0.98] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50"

export function PlayerImportView({
  mode,
  step,
  csvHeaders,
  columnMapping,
  rows,
  errorMessage,
  saveWarnings,
  onFileSelected,
  onColumnMappingChange,
  onConfirmMapping,
  onCellChange,
  onDeleteRow,
  onAddBlankRow,
  onSave,
  onClose,
}: PlayerImportViewProps) {
  // Fields selectable in the mapping step, filtered so mode-specific fields
  // only appear for the matching mode.
  const selectableFields = FIELD_ORDER.filter((f) => {
    if (f === "team_name") return mode.kind === "team"
    if (f === "class_name") return mode.kind === "individual"
    return true
  })

  // In the edit step, only render columns that some row actually uses (i.e.
  // fields that were mapped), keeping mode-specific columns filtered too.
  // Roster mode never goes through the upload/map steps (rows start pre-
  // filled from existing players, see org-player-roster-panel.tsx), so
  // `columnMapping` is always empty there -- show every selectable field
  // instead of falling back to just the name column.
  const activeFields =
    mode.kind === "roster"
      ? selectableFields
      : selectableFields.filter((field) => Object.values(columnMapping).includes(field))
  // Guarantee at least the name column so a blank table is still usable.
  const editFields = activeFields.length > 0 ? activeFields : ["display_name" as FieldKey]

  const isSaving = step === "saving"
  const isEditLike = step === "edit" || step === "saving"

  return (
    <div
      role="dialog"
      aria-modal="true"
      aria-label={mode.kind === "roster" ? "Rediger spillere" : "Importer spillere"}
      className="fixed inset-0 z-50 flex flex-col bg-background text-foreground"
    >
      {/* Header: title left, large close button right */}
      <header className="flex shrink-0 items-center justify-between gap-3 border-b border-border px-5 py-3.5 lg:px-8">
        <div className="flex min-w-0 flex-col">
          <h1 className="truncate text-lg font-extrabold lg:text-xl">
            {mode.kind === "roster" ? "Rediger spillere" : "Importer spillere"}
          </h1>
          <p className="truncate text-sm text-muted-foreground">
            {mode.kind === "team" ? "Lagturnering" : mode.kind === "individual" ? "Individuell turnering" : "Organisasjonens spillerpool"}
          </p>
        </div>
        <button
          type="button"
          onClick={onClose}
          aria-label={mode.kind === "roster" ? "Lukk redigering" : "Lukk import"}
          className={cn(
            "flex size-10 shrink-0 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:bg-accent/50 hover:text-foreground",
            "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
          )}
        >
          <X aria-hidden="true" className="size-6" />
        </button>
      </header>

      {/* Scrollable body */}
      <div className="min-h-0 flex-1 overflow-y-auto">
        <div
          className={cn(
            "mx-auto flex w-full flex-col gap-5 px-5 py-6 lg:px-8",
            // Wide steps use most of the screen; narrow steps stay readable.
            isEditLike ? "max-w-[110rem]" : "max-w-4xl",
          )}
        >
          {/* Global error box — shown in every step */}
          {errorMessage && (
            <div
              role="alert"
              className="flex items-start gap-3 rounded-xl border border-destructive/40 bg-destructive/10 p-4 text-destructive"
            >
              <AlertCircle aria-hidden="true" className="mt-0.5 size-5 shrink-0" />
              <p className="text-sm font-semibold leading-relaxed">{errorMessage}</p>
            </div>
          )}

          {step === "upload" && <UploadStep onFileSelected={onFileSelected} />}

          {step === "map" && (
            <MapStep
              csvHeaders={csvHeaders}
              columnMapping={columnMapping}
              selectableFields={selectableFields}
              rowCount={rows.length}
              onColumnMappingChange={onColumnMappingChange}
              onConfirmMapping={onConfirmMapping}
            />
          )}

          {isEditLike && (
            <EditTable
              mode={mode}
              rows={rows}
              editFields={editFields}
              onCellChange={onCellChange}
              onDeleteRow={onDeleteRow}
            />
          )}

          {step === "done" && <DoneStep mode={mode} saveWarnings={saveWarnings} onClose={onClose} />}
        </div>
      </div>

      {/* Sticky action bar — always visible for the edit/saving step so the
          organizer never has to scroll to reach "Lagre" with many rows. */}
      {isEditLike && (
        <footer className="shrink-0 border-t border-border bg-card/80 backdrop-blur">
          <div className="mx-auto flex w-full max-w-[110rem] flex-wrap items-center justify-between gap-3 px-5 py-3 lg:px-8">
            <div className="flex items-center gap-3">
              <button
                type="button"
                onClick={onAddBlankRow}
                disabled={isSaving}
                className={SECONDARY_BTN}
              >
                <Plus aria-hidden="true" className="size-5" />
                Legg til rad
              </button>
              <span className="text-sm font-semibold tabular-nums text-muted-foreground">
                {rows.length} {rows.length === 1 ? "rad" : "rader"}
              </span>
            </div>

            <button
              type="button"
              onClick={onSave}
              disabled={isSaving || rows.length === 0}
              aria-busy={isSaving}
              className={cn(PRIMARY_BTN, "px-6")}
            >
              {isSaving ? (
                <>
                  <span
                    aria-hidden="true"
                    className="size-5 animate-spin rounded-full border-2 border-primary-foreground/30 border-t-primary-foreground"
                  />
                  Lagrer …
                </>
              ) : (
                <>
                  Lagre {rows.length} {rows.length === 1 ? "spiller" : "spillere"}
                </>
              )}
            </button>
          </div>
        </footer>
      )}
    </div>
  )
}

function UploadStep({ onFileSelected }: { onFileSelected: (file: File) => void }) {
  const inputRef = useRef<HTMLInputElement>(null)

  function handleFiles(files: FileList | null) {
    const file = files?.[0]
    if (file) onFileSelected(file)
  }

  return (
    <label
      htmlFor="csv-file-input"
      onDragOver={(e) => e.preventDefault()}
      onDrop={(e) => {
        e.preventDefault()
        handleFiles(e.dataTransfer.files)
      }}
      className={cn(
        "mx-auto flex w-full max-w-3xl cursor-pointer flex-col items-center gap-5 rounded-3xl border-2 border-dashed border-border bg-card/50 px-8 py-16 text-center transition-colors",
        "hover:border-primary/60 hover:bg-accent/30",
        "focus-within:border-primary focus-within:ring-2 focus-within:ring-ring",
      )}
    >
      <span className="flex size-20 items-center justify-center rounded-2xl bg-primary/15 text-primary">
        <UploadCloud aria-hidden="true" className="size-10" />
      </span>
      <span className="flex flex-col gap-1.5">
        <span className="text-xl font-extrabold text-foreground">Dra CSV-filen hit</span>
        <span className="text-base leading-relaxed text-muted-foreground text-pretty">
          eller trykk for å velge en fil fra maskinen. Første rad må inneholde kolonnenavn.
        </span>
      </span>
      <span className={cn(PRIMARY_BTN, "px-6")}>
        <FileUp aria-hidden="true" className="size-5" />
        Velg fil
      </span>
      <input
        ref={inputRef}
        id="csv-file-input"
        type="file"
        accept=".csv,text/csv"
        className="sr-only"
        onChange={(e) => handleFiles(e.target.files)}
      />
    </label>
  )
}

function MapStep({
  csvHeaders,
  columnMapping,
  selectableFields,
  rowCount,
  onColumnMappingChange,
  onConfirmMapping,
}: {
  csvHeaders: string[]
  columnMapping: Record<number, FieldKey | "">
  selectableFields: FieldKey[]
  rowCount: number
  onColumnMappingChange: (columnIndex: number, field: FieldKey | "") => void
  onConfirmMapping: () => void
}) {
  return (
    <div className="flex flex-col gap-5">
      <div className="flex flex-col gap-1">
        <h2 className="text-xl font-extrabold text-foreground">Koble kolonner</h2>
        <p className="text-sm leading-relaxed text-muted-foreground text-pretty">
          Velg hvilket felt hver kolonne i filen tilsvarer. Kolonner du ikke trenger settes til{" "}
          <span className="font-semibold text-foreground">Ignorer</span>.
        </p>
      </div>

      {/* Multi-column grid so many mappings are visible at once on a wide
          screen without scrolling. CSV header left, field dropdown right. */}
      <ul className="grid grid-cols-1 gap-x-8 gap-y-3 lg:grid-cols-2 2xl:grid-cols-3">
        {csvHeaders.map((header, index) => {
          const selectId = `col-map-${index}`
          return (
            <li
              key={index}
              className="flex items-center justify-between gap-4 rounded-xl border border-border bg-card px-4 py-2.5"
            >
              <div className="flex min-w-0 flex-col">
                <span className="text-[0.7rem] font-bold uppercase tracking-wide text-muted-foreground">
                  Kolonne {index + 1}
                </span>
                <label htmlFor={selectId} className="truncate text-sm font-bold text-foreground">
                  {header || <span className="italic text-muted-foreground">(uten navn)</span>}
                </label>
              </div>
              <select
                id={selectId}
                value={columnMapping[index] ?? ""}
                onChange={(e) => onColumnMappingChange(index, e.target.value as FieldKey | "")}
                className={cn(CONTROL_BASE, "w-44 shrink-0 px-2.5 text-sm font-semibold")}
              >
                <option value="">Ignorer</option>
                {selectableFields.map((field) => (
                  <option key={field} value={field}>
                    {FIELD_LABELS[field]}
                  </option>
                ))}
              </select>
            </li>
          )
        })}
      </ul>

      <div className="flex justify-end">
        <button type="button" onClick={onConfirmMapping} className={cn(PRIMARY_BTN, "px-6")}>
          Neste: forhåndsvis {rowCount} {rowCount === 1 ? "rad" : "rader"}
        </button>
      </div>
    </div>
  )
}

function EditTable({
  mode,
  rows,
  editFields,
  onCellChange,
  onDeleteRow,
}: {
  mode: Mode
  rows: DraftRow[]
  editFields: FieldKey[]
  onCellChange: (rowKey: string, field: FieldKey, value: string) => void
  onDeleteRow: (rowKey: string) => void
}) {
  return (
    <div className="flex flex-col gap-4">
      <div className="flex flex-col gap-1">
        <h2 className="text-xl font-extrabold text-foreground">Kontroller spillerne</h2>
        <p className="text-sm leading-relaxed text-muted-foreground text-pretty">
          {mode.kind === "roster"
            ? "Rediger cellene direkte, og trykk Lagre. \"Slett\" fjerner raden herfra, men sletter IKKE spilleren fra organisasjonen -- det er ikke bygget ennå."
            : "Rediger cellene direkte før du lagrer. Du kan legge til eller slette rader."}
        </p>
      </div>

      {rows.length === 0 ? (
        <div className="flex flex-col items-center gap-2 rounded-2xl border border-dashed border-border bg-card/50 px-6 py-12 text-center">
          <p className="text-base font-bold text-foreground">Ingen rader ennå</p>
          <p className="text-sm text-muted-foreground">Legg til en rad for å komme i gang.</p>
        </div>
      ) : (
        // Horizontal scroll is isolated to this wrapper as a fallback for
        // narrow screens; on a wide screen every column is visible. `relative`
        // gives absolutely-positioned descendants (sr-only) a clipped block.
        <div className="relative min-w-0 overflow-x-auto rounded-2xl border border-border">
          <table className="w-full border-collapse text-left">
            <thead className="sticky top-0 z-10">
              <tr className="border-b border-border bg-muted">
                {editFields.map((field) => (
                  <th
                    key={field}
                    scope="col"
                    className="whitespace-nowrap px-3 py-2.5 text-xs font-extrabold uppercase tracking-wide text-muted-foreground"
                  >
                    {FIELD_LABELS[field]}
                  </th>
                ))}
                <th scope="col" className="px-3 py-2.5 text-right">
                  <span className="sr-only">Handlinger</span>
                </th>
              </tr>
            </thead>
            <tbody>
              {rows.map((row, rowIndex) => (
                <tr
                  key={row.key}
                  className={cn(
                    "border-b border-border last:border-b-0",
                    rowIndex % 2 === 1 && "bg-muted/30",
                  )}
                >
                  {editFields.map((field) => (
                    <td key={field} className="px-2 py-1.5 align-middle">
                      {field === "gender" ? (
                        <select
                          aria-label={`${FIELD_LABELS[field]} for rad ${rowIndex + 1}`}
                          value={row[field] ?? ""}
                          onChange={(e) => onCellChange(row.key, field, e.target.value)}
                          className={cn(CONTROL_BASE, FIELD_MIN_W[field], "w-full px-2 text-sm font-semibold")}
                        >
                          {GENDER_OPTIONS.map((opt) => (
                            <option key={opt.value} value={opt.value}>
                              {opt.label}
                            </option>
                          ))}
                        </select>
                      ) : field === "team_name" && mode.kind === "team" ? (
                        <select
                          aria-label={`Lag for rad ${rowIndex + 1}`}
                          value={row[field] ?? ""}
                          onChange={(e) => onCellChange(row.key, field, e.target.value)}
                          className={cn(CONTROL_BASE, FIELD_MIN_W[field], "w-full px-2 text-sm font-semibold")}
                        >
                          <option value="">—</option>
                          {mode.teams.map((t) => (
                            <option key={t.id} value={t.name}>
                              {t.name}
                            </option>
                          ))}
                        </select>
                      ) : field === "class_name" && mode.kind === "individual" ? (
                        <select
                          aria-label={`Klasse for rad ${rowIndex + 1}`}
                          value={row[field] ?? ""}
                          onChange={(e) => onCellChange(row.key, field, e.target.value)}
                          className={cn(CONTROL_BASE, FIELD_MIN_W[field], "w-full px-2 text-sm font-semibold")}
                        >
                          <option value="">—</option>
                          {mode.classes.map((c) => (
                            <option key={c.id} value={c.name}>
                              {c.name}
                            </option>
                          ))}
                        </select>
                      ) : (
                        <input
                          aria-label={`${FIELD_LABELS[field]} for rad ${rowIndex + 1}`}
                          value={row[field] ?? ""}
                          inputMode={field === "email" ? "email" : field === "mobile" ? "tel" : "text"}
                          onChange={(e) => onCellChange(row.key, field, e.target.value)}
                          className={cn(CONTROL_BASE, FIELD_MIN_W[field], "w-full px-2.5 text-sm")}
                        />
                      )}
                    </td>
                  ))}
                  <td className="px-2 py-1.5 align-middle">
                    <div className="flex justify-end">
                      <button
                        type="button"
                        onClick={() => onDeleteRow(row.key)}
                        aria-label={`Slett rad ${rowIndex + 1}${row.display_name ? ` for ${row.display_name}` : ""}`}
                        className={cn(
                          "inline-flex h-9 items-center gap-1.5 rounded-lg border border-border px-2.5 text-sm font-bold text-muted-foreground transition-colors",
                          "hover:border-destructive/40 hover:bg-destructive/10 hover:text-destructive active:scale-[0.98]",
                          "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
                        )}
                      >
                        <Trash2 aria-hidden="true" className="size-4" />
                        Slett
                      </button>
                    </div>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}
    </div>
  )
}

function DoneStep({ mode, saveWarnings, onClose }: { mode: Mode; saveWarnings: string[]; onClose: () => void }) {
  return (
    <div className="mx-auto flex w-full max-w-2xl flex-col items-center gap-6 py-10 text-center">
      <span className="flex size-20 items-center justify-center rounded-full bg-primary/15 text-primary">
        <CheckCircle2 aria-hidden="true" className="size-11" />
      </span>
      <div className="flex flex-col gap-1.5">
        <h2 className="text-2xl font-extrabold text-foreground">
          {mode.kind === "roster" ? "Endringene er lagret" : "Importen er fullført"}
        </h2>
        <p className="text-sm leading-relaxed text-muted-foreground text-pretty">
          {mode.kind === "roster" ? "Spillerpoolen er oppdatert." : "Spillerne er lagret i turneringen."}
        </p>
      </div>

      {saveWarnings.length > 0 && (
        // Warnings are informational, not errors — amber, not red.
        <div className="w-full rounded-2xl border border-brand-orange/40 bg-brand-orange/10 p-4 text-left">
          <div className="flex items-center gap-2 text-brand-orange">
            <TriangleAlert aria-hidden="true" className="size-5 shrink-0" />
            <h3 className="text-sm font-extrabold">
              {saveWarnings.length} {saveWarnings.length === 1 ? "rad trenger" : "rader trenger"}{" "}
              oppfølging
            </h3>
          </div>
          <ul className="mt-2 flex flex-col gap-1.5 pl-1">
            {saveWarnings.map((warning, i) => (
              <li key={i} className="flex gap-2 text-sm leading-relaxed text-foreground">
                <span aria-hidden="true" className="mt-2 size-1.5 shrink-0 rounded-full bg-brand-orange" />
                <span>{warning}</span>
              </li>
            ))}
          </ul>
        </div>
      )}

      <button type="button" onClick={onClose} className={cn(PRIMARY_BTN, "w-full sm:w-56")}>
        Lukk
      </button>
    </div>
  )
}
