// SnapshotEditPage — create or edit a balance snapshot at a given date.
//
// Issue #146 / Bilan #1b ships the route `/balance/snapshot` with two modes
// driven by the `?date=` query parameter:
//   - `?date=` absent → 'new' mode (date picker editable, defaults to today)
//   - `?date=YYYY-MM-DD` → 'edit' mode if a snapshot exists at that date,
//     otherwise 'new' mode pre-selected at that date (which mirrors the
//     "redirect to edit" flow when the user comes from the future
//     /balance overview's "Edit" link).
//
// The page itself only orchestrates: all DB work flows through
// `useSnapshotEditor`, the editor view through `SnapshotEditor`. Per spec
// (decisions row "Bouton Pré-remplir"), priced-kind prefill is a no-op
// here (the priced editor lands in #140).

import { useEffect, useMemo, useState } from "react";
import { useSearchParams, useNavigate } from "react-router-dom";
import { useTranslation } from "react-i18next";
import {
  ArrowLeft,
  Trash2,
  Save,
  Wallet,
  RotateCcw,
  AlertTriangle,
} from "lucide-react";
import { useSnapshotEditor } from "../hooks/useSnapshotEditor";
import SnapshotEditor from "../components/balance/SnapshotEditor";

export default function SnapshotEditPage() {
  const { t } = useTranslation();
  const [searchParams, setSearchParams] = useSearchParams();
  const navigate = useNavigate();

  const dateParam = searchParams.get("date");
  const editor = useSnapshotEditor({ dateParam });
  const { state } = editor;

  const [showDeleteModal, setShowDeleteModal] = useState(false);
  const [deleteConfirmText, setDeleteConfirmText] = useState("");

  // Reset the delete modal whenever the underlying snapshot changes (e.g.
  // after switching ?date=).
  useEffect(() => {
    setShowDeleteModal(false);
    setDeleteConfirmText("");
  }, [state.snapshot?.id]);

  const isEditMode = state.mode === "edit";
  const canPrefill = !!state.previousSnapshot;

  // Aggregate value across simple + detailed accounts (computed live as the
  // user types). A detailed account contributes the sum of its holdings'
  // quantity × unit_price (#213).
  const totalValue = useMemo(() => {
    let total = 0;
    let hasAny = false;
    for (const raw of Object.values(state.values)) {
      if (!raw) continue;
      const trimmed = String(raw).trim().replace(",", ".");
      const n = Number(trimmed);
      if (Number.isFinite(n)) {
        total += n;
        hasAny = true;
      }
    }
    for (const basket of Object.values(state.holdings)) {
      if (!basket) continue;
      for (const h of basket) {
        const qty = Number(String(h.quantity ?? "").trim().replace(",", "."));
        const price = Number(
          String(h.unit_price ?? "").trim().replace(",", ".")
        );
        if (Number.isFinite(qty) && Number.isFinite(price)) {
          total += qty * price;
          hasAny = true;
        }
      }
    }
    return hasAny ? total : null;
  }, [state.values, state.holdings]);

  const handleSave = async () => {
    try {
      await editor.save();
      // Keep the URL in sync with the saved date so a reload reopens the
      // right snapshot in edit mode. Covers both a fresh create (new → edit)
      // and an edit-mode date move (#200), where `?date=` still points at the
      // pre-move date until we update it here.
      setSearchParams({ date: state.snapshotDate }, { replace: true });
    } catch {
      // The hook surfaced the error via state.errorCode/state.error.
    }
  };

  const handleDelete = async () => {
    try {
      await editor.remove();
      navigate("/balance/accounts");
    } catch {
      // surfaced via state.error
    }
  };

  return (
    <div className={state.isLoading ? "opacity-50 pointer-events-none" : ""}>
      <div className="flex items-center gap-3 mb-6">
        <button
          type="button"
          onClick={() => navigate("/balance/accounts")}
          className="p-1.5 rounded hover:bg-[var(--muted)] text-[var(--muted-foreground)]"
          title={t("common.back")}
        >
          <ArrowLeft size={18} />
        </button>
        <Wallet size={24} className="text-[var(--primary)]" />
        <h1 className="text-2xl font-bold">
          {isEditMode
            ? t("balance.snapshot.page.editTitle")
            : t("balance.snapshot.page.newTitle")}
        </h1>
      </div>

      {state.error && (
        <div className="mb-4 p-3 rounded-lg bg-[var(--negative)]/10 text-[var(--negative)] text-sm border border-[var(--negative)]/20">
          {state.errorCode
            ? t(`balance.errors.${state.errorCode}`, {
                defaultValue: state.error,
              })
            : state.error}
        </div>
      )}

      <div className="bg-[var(--card)] rounded-xl border border-[var(--border)] p-4 mb-6">
        <div className="flex flex-col sm:flex-row sm:items-end gap-4">
          <div className="flex-1">
            <label
              className="block text-sm font-medium mb-1"
              htmlFor="snapshot-date"
            >
              {t("balance.snapshot.page.dateLabel")}
            </label>
            <input
              id="snapshot-date"
              type="date"
              value={state.snapshotDate}
              onChange={(e) => {
                const next = e.target.value;
                editor.setDate(next);
                // In 'new' mode, drive the route param so reloads stay
                // coherent and an existing snapshot at the chosen date flips
                // us into 'edit'. In 'edit' mode we deliberately DON'T sync
                // the URL: changing the date is a pending "move" applied on
                // save (#200), so reloading from the route would discard the
                // edit and reopen the original snapshot.
                if (!isEditMode) {
                  if (next) {
                    setSearchParams({ date: next }, { replace: true });
                  } else {
                    setSearchParams({}, { replace: true });
                  }
                }
                // WebKitGTK (Linux Tauri WebView) does not always dismiss the
                // native date popup after a value commit — user has to hit
                // Esc. Force-blur is a no-op on WebView2/WKWebView. See #177.
                e.currentTarget.blur();
              }}
              className="w-full px-3 py-2 rounded-lg border border-[var(--border)] bg-[var(--card)] text-sm focus:outline-none focus:ring-1 focus:ring-[var(--primary)]"
            />
            {isEditMode && (
              <p className="mt-1 text-xs text-[var(--muted-foreground)]">
                {t("balance.snapshot.page.dateMovableHint")}
              </p>
            )}
          </div>
          {totalValue !== null && (
            <div className="text-right">
              <div className="text-xs text-[var(--muted-foreground)]">
                {t("balance.snapshot.page.total")}
              </div>
              <div className="text-2xl font-semibold tabular-nums">
                {totalValue.toLocaleString(undefined, {
                  minimumFractionDigits: 2,
                  maximumFractionDigits: 2,
                })}
              </div>
            </div>
          )}
        </div>
      </div>

      {state.accounts.length === 0 && !state.isLoading ? (
        <div className="bg-[var(--card)] rounded-xl border border-[var(--border)] p-8 text-center text-[var(--muted-foreground)]">
          <p className="mb-3">{t("balance.snapshot.page.noAccounts")}</p>
          <button
            type="button"
            onClick={() => navigate("/balance/accounts")}
            className="px-4 py-2 rounded-lg bg-[var(--primary)] text-white text-sm font-medium hover:opacity-90"
          >
            {t("balance.snapshot.page.goToAccounts")}
          </button>
        </div>
      ) : (
        <SnapshotEditor
          accounts={state.accounts}
          categories={state.categories}
          values={state.values}
          holdings={state.holdings}
          securities={state.securities}
          onValueChange={editor.setLineValue}
          onAddHolding={editor.addHolding}
          onRemoveHolding={editor.removeHolding}
          onHoldingFieldChange={editor.setHoldingField}
          onHoldingSecurityPick={editor.setHoldingSecurity}
          onImportHoldings={editor.importHoldings}
          disabled={state.isSaving}
          snapshotDate={state.snapshotDate}
        />
      )}

      {/* Action bar */}
      <div className="mt-6 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3">
        <div className="flex items-center gap-2">
          <button
            type="button"
            onClick={editor.prefillFromPrevious}
            disabled={!canPrefill || state.isSaving}
            title={
              canPrefill
                ? t("balance.snapshot.page.prefillTooltip", {
                    date: state.previousSnapshot?.snapshot_date,
                  })
                : t("balance.snapshot.page.prefillNoPrevious")
            }
            className="flex items-center gap-2 px-3 py-2 rounded-lg border border-[var(--border)] text-sm hover:bg-[var(--muted)] disabled:opacity-50 disabled:cursor-not-allowed"
          >
            <RotateCcw size={14} />
            {t("balance.snapshot.page.prefill")}
          </button>
          {isEditMode && (
            <button
              type="button"
              onClick={() => setShowDeleteModal(true)}
              disabled={state.isSaving}
              className="flex items-center gap-2 px-3 py-2 rounded-lg border border-[var(--negative)]/40 text-sm text-[var(--negative)] hover:bg-[var(--negative)]/10 disabled:opacity-50"
            >
              <Trash2 size={14} />
              {t("balance.snapshot.page.delete")}
            </button>
          )}
        </div>
        <div className="flex items-center gap-2">
          <button
            type="button"
            onClick={() => navigate("/balance/accounts")}
            disabled={state.isSaving}
            className="px-4 py-2 rounded-lg border border-[var(--border)] text-sm hover:bg-[var(--muted)] disabled:opacity-50"
          >
            {t("common.cancel")}
          </button>
          <button
            type="button"
            onClick={handleSave}
            disabled={
              state.isSaving ||
              state.isLoading ||
              state.accounts.length === 0 ||
              !state.snapshotDate
            }
            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"
          >
            <Save size={14} />
            {isEditMode
              ? t("balance.snapshot.page.save")
              : t("balance.snapshot.page.create")}
          </button>
        </div>
      </div>

      {/* Delete confirmation modal — double-confirmation requires retyping
          the snapshot date. */}
      {showDeleteModal && state.snapshot && (
        <DeleteConfirmModal
          snapshotDate={state.snapshot.snapshot_date}
          confirmText={deleteConfirmText}
          onConfirmTextChange={setDeleteConfirmText}
          isSaving={state.isSaving}
          onCancel={() => {
            setShowDeleteModal(false);
            setDeleteConfirmText("");
          }}
          onConfirm={handleDelete}
        />
      )}
    </div>
  );
}

// -----------------------------------------------------------------------------
// Internal components
// -----------------------------------------------------------------------------

function DeleteConfirmModal({
  snapshotDate,
  confirmText,
  onConfirmTextChange,
  isSaving,
  onCancel,
  onConfirm,
}: {
  snapshotDate: string;
  confirmText: string;
  onConfirmTextChange: (next: string) => void;
  isSaving: boolean;
  onCancel: () => void;
  onConfirm: () => void;
}) {
  const { t } = useTranslation();
  const isMatch = confirmText.trim() === snapshotDate;
  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-md w-full p-6">
        <div className="flex items-start gap-3 mb-4">
          <div className="p-2 rounded-full bg-[var(--negative)]/10 text-[var(--negative)]">
            <AlertTriangle size={20} />
          </div>
          <div>
            <h2 className="text-lg font-semibold">
              {t("balance.snapshot.delete.title")}
            </h2>
            <p className="mt-1 text-sm text-[var(--muted-foreground)]">
              {t("balance.snapshot.delete.body", { date: snapshotDate })}
            </p>
          </div>
        </div>
        <label
          className="block text-sm font-medium mb-1"
          htmlFor="delete-confirm-input"
        >
          {t("balance.snapshot.delete.confirmLabel", { date: snapshotDate })}
        </label>
        <input
          id="delete-confirm-input"
          type="text"
          value={confirmText}
          onChange={(e) => onConfirmTextChange(e.target.value)}
          placeholder={snapshotDate}
          autoComplete="off"
          className="w-full px-3 py-2 rounded-lg border border-[var(--border)] bg-[var(--background)] text-sm focus:outline-none focus:ring-1 focus:ring-[var(--negative)]"
        />
        <div className="flex justify-end gap-2 mt-4">
          <button
            type="button"
            onClick={onCancel}
            disabled={isSaving}
            className="px-4 py-2 rounded-lg border border-[var(--border)] text-sm hover:bg-[var(--muted)] disabled:opacity-50"
          >
            {t("common.cancel")}
          </button>
          <button
            type="button"
            onClick={onConfirm}
            disabled={isSaving || !isMatch}
            className="px-4 py-2 rounded-lg bg-[var(--negative)] text-white text-sm font-medium hover:opacity-90 disabled:opacity-50"
          >
            {t("balance.snapshot.delete.confirm")}
          </button>
        </div>
      </div>
    </div>
  );
}
