// HoldingsCsvImportModal — bulk-import a detailed account's positions from a
// CSV instead of typing them one by one (Issue #245).
//
// Flow (all frontend — the save path is unchanged):
//   1. pick a CSV file (native dialog, reusing the existing `pick_import_file`
//      Rust command with a CSV filter);
//   2. detect its encoding (`detect_encoding`, utf-8 fallback) + read it
//      (`read_file_content`);
//   3. `analyzeHoldingsCsv` preprocesses, detects the delimiter/header and the
//      symbol / quantity / unit_price / book_cost columns (flexible price
//      detection: no price column ⇒ mapping stays null);
//   4. the user reviews/adjusts the mapping in a small editor + preview;
//   5. on confirm we hand the DATA rows + mapping up to the editor hook, which
//      builds `HoldingDraft`s (FR numbers, duplicate-symbol merge) and merges
//      them into the account's basket. The user then fetches/types any missing
//      price and saves through the normal atomic path.
//
// The component owns the file/parse lifecycle; the actual draft building and
// basket merge live in `useSnapshotEditor` so they stay pure + unit-tested.

import { useCallback, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { invoke } from "@tauri-apps/api/core";
import { Upload, X, AlertTriangle, FileSpreadsheet } from "lucide-react";
import {
  analyzeHoldingsCsv,
  type HoldingColumnMapping,
  type HoldingCsvAnalysis,
} from "../../utils/csvAutoDetect";
import { normalizeSecuritySymbol } from "../../services/balance.service";

interface Props {
  accountName: string;
  /** Called with the parsed DATA rows + the confirmed column mapping. */
  onImport: (rows: string[][], mapping: HoldingColumnMapping) => void;
  onClose: () => void;
}

type Step = "select" | "loading" | "map" | "error";

const PREVIEW_ROWS = 5;

export default function HoldingsCsvImportModal({
  accountName,
  onImport,
  onClose,
}: Props) {
  const { t } = useTranslation();
  const [step, setStep] = useState<Step>("select");
  const [analysis, setAnalysis] = useState<HoldingCsvAnalysis | null>(null);
  const [mapping, setMapping] = useState<HoldingColumnMapping | null>(null);
  const [errorMsg, setErrorMsg] = useState<string>("");

  const pickAndAnalyze = useCallback(async () => {
    setStep("loading");
    setErrorMsg("");
    try {
      const filePath = await invoke<string | null>("pick_import_file", {
        filters: [["CSV", ["csv", "txt"]]],
      });
      if (!filePath) {
        // User cancelled the native dialog — return to the select step.
        setStep("select");
        return;
      }

      let encoding = "utf-8";
      try {
        encoding = await invoke<string>("detect_encoding", {
          filePath,
        });
      } catch {
        // fall back to utf-8
      }

      const content = await invoke<string>("read_file_content", {
        filePath,
        encoding,
      });

      const result = analyzeHoldingsCsv(content);
      if (!result) {
        setErrorMsg(t("balance.snapshot.detailed.importCsv.detectError"));
        setStep("error");
        return;
      }
      setAnalysis(result);
      setMapping(result.mapping);
      setStep("map");
    } catch (e) {
      setErrorMsg(
        e instanceof Error
          ? e.message
          : t("balance.snapshot.detailed.importCsv.readError")
      );
      setStep("error");
    }
  }, [t]);

  const columnOptions = useMemo(() => {
    if (!analysis) return null;
    return analysis.headers.map((h, i) => (
      <option key={i} value={i}>
        {i}: {h}
      </option>
    ));
  }, [analysis]);

  const preview = useMemo(() => {
    if (!analysis || !mapping) return [];
    return analysis.rows.slice(0, PREVIEW_ROWS).map((row) => {
      const symbol = normalizeSecuritySymbol((row[mapping.symbol] ?? "").trim());
      const qty = (row[mapping.quantity] ?? "").trim();
      const price =
        mapping.unit_price !== null
          ? (row[mapping.unit_price] ?? "").trim()
          : "";
      const book =
        mapping.book_cost !== null ? (row[mapping.book_cost] ?? "").trim() : "";
      return { symbol, qty, price, book };
    });
  }, [analysis, mapping]);

  // Count the distinct, non-blank symbols that would be imported (after merge).
  const importableCount = useMemo(() => {
    if (!analysis || !mapping) return 0;
    const seen = new Set<string>();
    for (const row of analysis.rows) {
      const s = normalizeSecuritySymbol((row[mapping.symbol] ?? "").trim());
      if (s) seen.add(s);
    }
    return seen.size;
  }, [analysis, mapping]);

  const handleImport = () => {
    if (!analysis || !mapping) return;
    onImport(analysis.rows, mapping);
    onClose();
  };

  const selectClass =
    "w-full px-3 py-2 text-sm rounded-lg border border-[var(--border)] bg-[var(--card)] text-[var(--foreground)] focus:outline-none focus:ring-1 focus:ring-[var(--primary)]";

  const setMappingField = (
    field: keyof HoldingColumnMapping,
    raw: string
  ) => {
    if (!mapping) return;
    const parsed = parseInt(raw, 10);
    const next: number | null =
      Number.isNaN(parsed) || parsed < 0 ? null : parsed;
    setMapping({ ...mapping, [field]: next });
  };

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4">
      <div className="bg-[var(--card)] rounded-xl border border-[var(--border)] shadow-xl max-w-lg w-full p-6 max-h-[90vh] overflow-y-auto">
        <div className="flex items-start justify-between gap-3 mb-4">
          <div className="flex items-center gap-2 min-w-0">
            <FileSpreadsheet size={20} className="text-[var(--primary)]" />
            <h2 className="text-lg font-semibold truncate">
              {t("balance.snapshot.detailed.importCsv.title")}
            </h2>
          </div>
          <button
            type="button"
            onClick={onClose}
            className="p-1 rounded text-[var(--muted-foreground)] hover:bg-[var(--muted)]"
            aria-label={t("common.cancel")}
          >
            <X size={18} />
          </button>
        </div>

        <p className="text-sm text-[var(--muted-foreground)] mb-4">
          {t("balance.snapshot.detailed.importCsv.intro", {
            account: accountName,
          })}
        </p>

        {(step === "select" || step === "loading") && (
          <div className="flex flex-col items-center gap-3 py-6">
            <button
              type="button"
              onClick={pickAndAnalyze}
              disabled={step === "loading"}
              className="flex items-center gap-2 px-4 py-2 rounded-lg bg-[var(--primary)] text-white text-sm font-medium hover:opacity-90 disabled:opacity-50"
            >
              <Upload size={16} />
              {step === "loading"
                ? t("balance.snapshot.detailed.importCsv.loading")
                : t("balance.snapshot.detailed.importCsv.selectFile")}
            </button>
            <p className="text-xs text-[var(--muted-foreground)] text-center">
              {t("balance.snapshot.detailed.importCsv.hint")}
            </p>
          </div>
        )}

        {step === "error" && (
          <div className="py-4">
            <div className="flex items-start gap-2 p-3 rounded-lg bg-[var(--negative)]/10 text-[var(--negative)] text-sm border border-[var(--negative)]/20">
              <AlertTriangle size={16} className="mt-0.5 shrink-0" />
              <span>{errorMsg}</span>
            </div>
            <div className="flex justify-end mt-4">
              <button
                type="button"
                onClick={() => setStep("select")}
                className="px-4 py-2 rounded-lg border border-[var(--border)] text-sm hover:bg-[var(--muted)]"
              >
                {t("balance.snapshot.detailed.importCsv.retry")}
              </button>
            </div>
          </div>
        )}

        {step === "map" && analysis && mapping && (
          <div className="space-y-4">
            <div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
              <div>
                <label className="block text-xs font-medium text-[var(--muted-foreground)] mb-1">
                  {t("balance.snapshot.detailed.importCsv.symbolColumn")}
                </label>
                <select
                  value={mapping.symbol}
                  onChange={(e) => setMappingField("symbol", e.target.value)}
                  className={selectClass}
                >
                  {columnOptions}
                </select>
              </div>
              <div>
                <label className="block text-xs font-medium text-[var(--muted-foreground)] mb-1">
                  {t("balance.snapshot.detailed.importCsv.quantityColumn")}
                </label>
                <select
                  value={mapping.quantity}
                  onChange={(e) => setMappingField("quantity", e.target.value)}
                  className={selectClass}
                >
                  {columnOptions}
                </select>
              </div>
              <div>
                <label className="block text-xs font-medium text-[var(--muted-foreground)] mb-1">
                  {t("balance.snapshot.detailed.importCsv.priceColumn")}
                </label>
                <select
                  value={mapping.unit_price ?? -1}
                  onChange={(e) => setMappingField("unit_price", e.target.value)}
                  className={selectClass}
                >
                  <option value={-1}>
                    {t("balance.snapshot.detailed.importCsv.noColumn")}
                  </option>
                  {columnOptions}
                </select>
              </div>
              <div>
                <label className="block text-xs font-medium text-[var(--muted-foreground)] mb-1">
                  {t("balance.snapshot.detailed.importCsv.bookCostColumn")}
                </label>
                <select
                  value={mapping.book_cost ?? -1}
                  onChange={(e) => setMappingField("book_cost", e.target.value)}
                  className={selectClass}
                >
                  <option value={-1}>
                    {t("balance.snapshot.detailed.importCsv.noColumn")}
                  </option>
                  {columnOptions}
                </select>
              </div>
            </div>

            {mapping.unit_price === null && (
              <p className="text-xs text-[var(--muted-foreground)] italic">
                {t("balance.snapshot.detailed.importCsv.noPriceNote")}
              </p>
            )}

            {/* Preview of the first rows as they will be imported. */}
            <div className="rounded-lg border border-[var(--border)] overflow-x-auto">
              <table className="w-full text-xs">
                <thead>
                  <tr className="bg-[var(--muted)] text-left">
                    <th className="px-2 py-1.5 font-medium">
                      {t("balance.snapshot.detailed.col.title")}
                    </th>
                    <th className="px-2 py-1.5 font-medium text-right">
                      {t("balance.snapshot.detailed.col.quantity")}
                    </th>
                    <th className="px-2 py-1.5 font-medium text-right">
                      {t("balance.snapshot.detailed.col.unitPrice")}
                    </th>
                    <th className="px-2 py-1.5 font-medium text-right">
                      {t("balance.snapshot.detailed.col.bookCost")}
                    </th>
                  </tr>
                </thead>
                <tbody>
                  {preview.map((r, i) => (
                    <tr
                      key={i}
                      className="border-t border-[var(--border)] tabular-nums"
                    >
                      <td className="px-2 py-1.5 font-medium">
                        {r.symbol || "—"}
                      </td>
                      <td className="px-2 py-1.5 text-right">{r.qty || "—"}</td>
                      <td className="px-2 py-1.5 text-right">
                        {r.price || "—"}
                      </td>
                      <td className="px-2 py-1.5 text-right">{r.book || "—"}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>

            <p className="text-xs text-[var(--muted-foreground)]">
              {t("balance.snapshot.detailed.importCsv.summary", {
                count: importableCount,
              })}
            </p>

            <div className="flex justify-end gap-2 pt-1">
              <button
                type="button"
                onClick={onClose}
                className="px-4 py-2 rounded-lg border border-[var(--border)] text-sm hover:bg-[var(--muted)]"
              >
                {t("common.cancel")}
              </button>
              <button
                type="button"
                onClick={handleImport}
                disabled={importableCount === 0}
                className="flex items-center gap-2 px-4 py-2 rounded-lg bg-[var(--primary)] text-white text-sm font-medium hover:opacity-90 disabled:opacity-50"
              >
                <Upload size={14} />
                {t("balance.snapshot.detailed.importCsv.import")}
              </button>
            </div>
          </div>
        )}
      </div>
    </div>
  );
}
