"use client";

import { useRef, useState } from "react";
import { api, ImportResult, ImportRow } from "@/lib/api";
import { useLocale } from "@/i18n/LocaleProvider";
import { Button, Modal, Numeric, Stepper } from "@/components/ui";
import { parseCsv, templateCsv } from "@/lib/csvImport";

/**
 * Bulk vehicle import.
 *
 * <p>Two steps by design, and the first one never writes: the file is always validated server-side
 * as a dry run and the result shown before anything is applied. A file with any bad row is rejected
 * whole, so the operator fixes one spreadsheet instead of discovering problems one vehicle at a
 * time - and row numbers here match their spreadsheet's line numbers.
 */
export function ImportModal({
  open,
  onClose,
  onImported,
}: {
  open: boolean;
  onClose: () => void;
  onImported: () => void;
}) {
  const { t } = useLocale();
  const fileRef = useRef<HTMLInputElement>(null);
  const [text, setText] = useState("");
  const [rows, setRows] = useState<ImportRow[] | null>(null);
  const [parseError, setParseError] = useState<string | null>(null);
  const [result, setResult] = useState<ImportResult | null>(null);
  const [applied, setApplied] = useState(false);
  const [busy, setBusy] = useState(false);

  function reset() {
    setText("");
    setRows(null);
    setParseError(null);
    setResult(null);
    setApplied(false);
    setBusy(false);
  }

  function close() {
    reset();
    onClose();
  }

  async function readFile(file: File) {
    setText(await file.text());
    setParseError(null);
  }

  async function check() {
    const parsed = parseCsv(text);
    if (!parsed.ok) {
      const messages = {
        empty: "imp.errEmpty",
        noHeader: "imp.errNoHeader",
        noQrColumn: "imp.errNoQr",
        noRows: "imp.errNoRows",
      } as const;
      setParseError(t(messages[parsed.error] as never));
      return;
    }
    setParseError(null);
    setRows(parsed.rows);
    setBusy(true);
    try {
      setResult(await api.importVehicles(true, parsed.rows));
    } finally {
      setBusy(false);
    }
  }

  async function apply() {
    if (!rows) return;
    setBusy(true);
    try {
      const r = await api.importVehicles(false, rows);
      setResult(r);
      setApplied(r.applied);
      if (r.applied) onImported();
    } finally {
      setBusy(false);
    }
  }

  function downloadTemplate() {
    const blob = new Blob([templateCsv()], { type: "text/csv;charset=utf-8" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = "beebbeeb-vehicles.csv";
    a.click();
    URL.revokeObjectURL(url);
  }

  const step = result ? 2 : 1;
  const rejected = !!result && result.errors.length > 0;

  return (
    <Modal
      open={open}
      onClose={close}
      wide
      title={t("imp.title")}
      description={t("imp.subtitle")}
      actions={
        applied ? (
          <Button variant="primary" onClick={close}>
            {t("common.close")}
          </Button>
        ) : (
          <>
            <Button onClick={result ? () => setResult(null) : close}>
              {result ? t("imp.back") : t("common.cancel")}
            </Button>
            {result && !rejected ? (
              <Button variant="primary" onClick={apply} disabled={busy}>
                {t("imp.apply")}
              </Button>
            ) : (
              !result && (
                <Button
                  variant="primary"
                  onClick={check}
                  disabled={busy || text.trim().length === 0}
                >
                  {t("imp.check")}
                </Button>
              )
            )}
          </>
        )
      }
    >
      <div className="space-y-5">
        <Stepper step={step} total={2} />

        {!result && (
          <div className="space-y-3">
            <div className="flex flex-wrap items-center gap-3">
              <input
                ref={fileRef}
                type="file"
                accept=".csv,text/csv"
                className="hidden"
                onChange={(e) => {
                  const f = e.target.files?.[0];
                  if (f) readFile(f);
                }}
              />
              <Button onClick={() => fileRef.current?.click()}>
                {t("imp.choose")}
              </Button>
              <Button variant="ghost" onClick={downloadTemplate}>
                {t("imp.template")}
              </Button>
            </div>

            <textarea
              className="field h-48 font-mono text-xs"
              dir="ltr"
              placeholder={t("imp.paste")}
              value={text}
              onChange={(e) => setText(e.target.value)}
            />
            <p className="text-xs text-muted">{t("imp.columns")}</p>
            {parseError && <p className="text-sm text-danger">{parseError}</p>}
          </div>
        )}

        {result && rejected && (
          <div className="space-y-3">
            <div className="card tint tone-danger p-4">
              <p className="text-sm font-semibold">{t("imp.rejected")}</p>
              <p className="mt-1 text-sm">{t("imp.rejectedBody")}</p>
            </div>
            <div className="overflow-x-auto">
              <table className="w-full text-sm">
                <thead>
                  <tr className="border-b border-line text-start text-xs text-muted">
                    <th className="p-2 text-start font-medium">{t("imp.colRow")}</th>
                    <th className="p-2 text-start font-medium">{t("imp.colField")}</th>
                    <th className="p-2 text-start font-medium">{t("imp.colProblem")}</th>
                  </tr>
                </thead>
                <tbody className="divide-y divide-line">
                  {result.errors.map((e, i) => (
                    <tr key={i}>
                      <td className="p-2">
                        <Numeric>{e.row}</Numeric>
                      </td>
                      <td className="p-2 font-mono text-xs text-muted">
                        {e.field ?? "-"}
                      </td>
                      <td className="p-2">{e.message}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          </div>
        )}

        {result && !rejected && (
          <div className="space-y-3">
            {applied && (
              <div className="card tint tone-success p-4">
                <p className="text-sm font-semibold">{t("imp.done")}</p>
              </div>
            )}
            <div className="grid gap-3 sm:grid-cols-3">
              <Summary value={result.received} label={t("imp.rowsParsed")} />
              <Summary
                value={result.created}
                label={applied ? t("imp.created") : t("imp.willCreate")}
                tone="text-success"
              />
              <Summary
                value={result.updated}
                label={applied ? t("imp.updated") : t("imp.willUpdate")}
              />
            </div>
          </div>
        )}
      </div>
    </Modal>
  );
}

function Summary({
  value,
  label,
  tone = "",
}: {
  value: number;
  label: string;
  tone?: string;
}) {
  return (
    <div className="rounded-card border border-line bg-surface p-4">
      <div className={`text-2xl font-bold ${tone}`}>
        <Numeric>{value}</Numeric>
      </div>
      <div className="mt-1 text-[13px] text-muted">{label}</div>
    </div>
  );
}
