"use client";

// Die Bestandsaufnahme: alles erfassen, was heute da ist.
//
// Der einzige Sammel-Dialog, der geblieben ist. Er arbeitet ausschliesslich über die
// bestehenden Endpunkte -- was er schreibt, hätte man auch einzeln über die Matrix erfassen
// können; er nimmt einem nur das Suchen ab.
//
// Erfasst werden NUR Tatsachen: Kontostand, Guthaben, Kaufpreis, Restschuld. Renditen,
// Lohnentwicklung und Teuerung stehen bewusst nicht hier -- sie sind Annahmen, und eine
// Annahme gilt immer nur für einen Zeitraum. Sie werden in den Phasenzellen der Matrix
// gesetzt und dort bestätigt (SPEZIFIKATION 3.14).

import { useState } from "react";
import { Check, Plus, Trash2 } from "lucide-react";
import { api } from "@/lib/api-client";
import { Button, Modal, useConfirm } from "@/components/ui";
import { MoneyField, NumberField, SelectField, TextField } from "@/components/FormField";
import { formatChf } from "@/lib/format";
import { CATEGORY_LABELS, ownerLabel, num, type PhaseData } from "@/lib/elements";
import type { PlanInput } from "@/lib/types";

type Scope = "HOUSEHOLD" | "PERSON_A" | "PERSON_B";

interface Kind {
  key: string;
  category: string;
  // Beschriftung des Knopfs. Bewusst der KATEGORIENAME und keine erfundene Umgangssprache:
  // Die Matrix, die Rechenwege und der PDF-Bericht sprechen dieselbe Sprache -- wer hier eine
  // andere Vokabel lernt, sucht sie spaeter vergeblich. Die Alltagssprache steht in `hint`.
  label: string;
  // Vorschlag fuer den Namen des angelegten Elements. Hier darf es konkret werden: Die
  // Kategorie ist "Ausgaben", die Zeile heisst "Lebenshaltung".
  defaultName: string;
  hint: string;
  personOnly?: boolean;
  // SCHRITT 1 -- der Bestand von heute. Nur Zahlen, die man nachschlagen kann: Kontostand,
  // Guthaben, Kaufpreis, Restschuld.
  baseFields: (v: PhaseData, set: (p: Partial<PhaseData>) => void) => React.ReactNode;
  // SCHRITT 2 -- die Annahmen fuer EINE Lebensphase. Alles, was pro Jahr geschieht und sich
  // von Phase zu Phase aendern darf: Renditen, Lohnentwicklung, Wertsteigerung, Zins.
  //
  // Die Trennung ist der Kern: Ein Guthaben ist eine Tatsache, eine Rendite eine Annahme --
  // und Annahmen gelten immer nur fuer einen Zeitraum. Bis 0.37 standen beide zusammen in der
  // Bestandsaufnahme, wodurch eine Annahme wie eine Tatsache aussah.
  phaseFields?: (v: PhaseData, set: (p: Partial<PhaseData>) => void) => React.ReactNode;
}

const KINDS: Kind[] = [
  {
    key: "income",
    category: "INCOME",
    label: "Einkommen",
    defaultName: "Lohn",
    hint: "Dein Nettolohn – das, was auf dem Konto ankommt.",
    personOnly: true,
    baseFields: (v, set) => (
      <MoneyField
        label="Nettolohn pro Jahr"
        help="Was tatsächlich aufs Konto kommt, nach allen Abzügen. FPT rechnet für die AHV intern auf den Bruttolohn hoch."
        value={num(v.amount)}
        onChange={(x) => set({ amount: x })}
      />
    ),
    phaseFields: (v, set) => (
      <NumberField
        label="Jährliche Lohnerhöhung (%)"
        help="Nominal, also inklusive Teuerung. 1 % ist ein vorsichtiger Ausgangswert."
        step={0.5}
        value={num(v.teuerungsausgleich, 1)}
        onChange={(x) => set({ teuerungsausgleich: x })}
      />
    ),
  },
  {
    key: "expense",
    category: "EXPENSE",
    label: "Ausgaben",
    defaultName: "Lebenshaltung",
    hint: "Alles, was du im Jahr ausgibst – Wohnen, Essen, Versicherungen, Freizeit.",
    baseFields: (v, set) => (
      <MoneyField
        label="Ausgaben pro Jahr"
        help="In heutiger Kaufkraft. Die Teuerung rechnet FPT selbst dazu."
        value={num(v.amount)}
        onChange={(x) => set({ amount: x })}
      />
    ),
    phaseFields: (v, set) => (
      <NumberField
        label="Jährliche Teuerung (%)"
        help="Leer lassen heisst: die Inflationsannahme des Szenarios. Eine eigene Zahl nur, wenn du für diese Ausgaben etwas anderes erwartest."
        step={0.25}
        value={num(v.teuerungsausgleich)}
        onChange={(x) => set({ teuerungsausgleich: x })}
      />
    ),
  },
  {
    key: "pk",
    category: "PENSION_FUND",
    label: "Pensionskasse",
    defaultName: "Pensionskasse",
    hint: "Dein Altersguthaben laut PK-Ausweis.",
    personOnly: true,
    baseFields: (v, set) => (
      <MoneyField
        label="Altersguthaben heute"
        help="Steht auf deinem Vorsorgeausweis."
        value={num(v.currentValue)}
        onChange={(x) => set({ currentValue: x })}
      />
    ),
    phaseFields: (v, set) => (
      <>
        <NumberField
          label="Verzinsung (%/Jahr)"
          help="Der BVG-Mindestzins liegt aktuell tief; viele Kassen verzinsen etwas darüber."
          step={0.25}
          value={num(v.expectedReturn, 1.25)}
          onChange={(x) => set({ expectedReturn: x })}
        />
        {/* Der PK-Beitrag steht hier und nicht bei der Sparquote: Er stammt aus dem
            Bruttolohn und belastet das Cash-Konto nicht -- aus der Quote liesse er sich
            gar nicht verteilen (SPEZIFIKATION 4.6.3). */}
        <MoneyField
          label="Jährlicher Beitrag (Arbeitnehmer + Arbeitgeber)"
          help="Die Altersgutschrift laut Vorsorgeausweis. Sie kommt aus dem Bruttolohn und schmälert deine Sparquote deshalb nicht."
          value={num(v.annualContribution)}
          onChange={(x) => set({ annualContribution: x })}
        />
      </>
    ),
  },
  {
    key: "p3a",
    category: "PILLAR_3A",
    label: "Säule 3a",
    defaultName: "Säule 3a",
    hint: "Ein Konto oder Depot der gebundenen Vorsorge. Mehrere Konten legst du einzeln an.",
    personOnly: true,
    baseFields: (v, set) => (
      <MoneyField label="Guthaben heute" value={num(v.currentValue)} onChange={(x) => set({ currentValue: x })} />
    ),
    phaseFields: (v, set) => (
      <NumberField
        label="Erwartete Rendite (%/Jahr)"
        help="Auf einem Konto praktisch 0, in einer Wertschriftenlösung deutlich mehr."
        step={0.5}
        value={num(v.expectedReturn, 2)}
        onChange={(x) => set({ expectedReturn: x })}
      />
    ),
  },
  {
    key: "etf",
    category: "OTHER_ASSET",
    label: "Sonstiges Vermögen",
    defaultName: "Wertschriften",
    hint: "Depot, ETF, Sparkonto – alles freie Vermögen ausser dem Cash-Konto.",
    baseFields: (v, set) => (
      <MoneyField label="Wert heute" value={num(v.startValue)} onChange={(x) => set({ startValue: x })} />
    ),
    phaseFields: (v, set) => (
      <NumberField
        label="Erwartete Rendite (%/Jahr)"
        help="Langfristiger Durchschnitt. Für ein gemischtes Portfolio sind 3 bis 5 % ein üblicher Ansatz."
        step={0.5}
        value={num(v.expectedReturn, 4)}
        onChange={(x) => set({ expectedReturn: x })}
      />
    ),
  },
  {
    key: "re",
    category: "REAL_ESTATE",
    label: "Immobilie",
    defaultName: "Wohneigentum",
    hint: "Haus oder Wohnung samt Hypothek.",
    baseFields: (v, set) => (
      <>
        <MoneyField
          label="Kaufpreis"
          help="Der ursprüngliche Kaufpreis – Grundlage der Grundstückgewinnsteuer bei einem späteren Verkauf."
          value={num(v.purchasePrice)}
          onChange={(x) => set({ purchasePrice: x })}
        />
        <MoneyField label="Hypothek heute" value={num(v.mortgage)} onChange={(x) => set({ mortgage: x })} />
      </>
    ),
    phaseFields: (v, set) => (
      <>
        <NumberField
          label="Hypothekarzins (%)"
          step={0.25}
          value={num(v.interestRate, 2)}
          onChange={(x) => set({ interestRate: x })}
        />
        <NumberField
          label="Wertsteigerung (%/Jahr)"
          help="Auf den Wert der Liegenschaft, nicht auf dein Eigenkapital – dort wirkt sie gehebelt."
          step={0.25}
          value={num(v.valueGrowth, 1)}
          onChange={(x) => set({ valueGrowth: x })}
        />
        <div className="sm:col-span-2">
          <SelectField
            label="Sind die Hypothekarzinsen in deinen Ausgaben schon enthalten?"
            help="Wenn ja, rechnet FPT sie nicht noch einmal dazu – sonst zählten sie doppelt."
            value={v.interestHandling ?? "INCLUDED"}
            onChange={(x: "INCLUDED" | "ADD") => set({ interestHandling: x })}
            options={[
              { value: "INCLUDED", label: "Ja, sind in der Lebenshaltung enthalten" },
              { value: "ADD", label: "Nein, bitte zusätzlich rechnen" },
            ]}
          />
        </div>
      </>
    ),
  },
  {
    key: "debt",
    category: "OTHER_DEBT",
    label: "Sonstige Schulden",
    defaultName: "Schulden",
    hint: "Kredite ausserhalb der Hypothek.",
    baseFields: (v, set) => (
      <MoneyField label="Restschuld heute" value={num(v.startValue)} onChange={(x) => set({ startValue: x })} />
    ),
  },
];

// Der Entwurf des GANZEN Schritts, nicht der einzelnen Karte.
//
// Zwei Gruende dafuer, dass er hier oben liegt und nicht in der Karte: Beim Wechsel des
// Reiters verschwinden die Karten des vorigen Bereichs vom Bildschirm -- mit ihrem eigenen
// Zustand waeren alle getippten Zahlen still weg. Und die Summe "Vermoegen heute" laesst sich
// nur berechnen, wenn alle Entwuerfe an EINEM Ort liegen.
export interface InventoryDraft {
  base: Record<string, PhaseData>;
  names: Record<string, string>;
  // Cash ist kein Element, sondern eine Eigenschaft des Szenarios (`Scenario.initialCash`) --
  // deshalb kein Plus-Knopf, sondern ein festes Feld. Es fehlte bis 0.39 ganz: Die Summe
  // «Vermögen heute» rechnete es bereits mit, erfassen konnte man es hier aber nirgends.
  // `null` = unberührt (dann wird beim Speichern auch nichts geschrieben).
  cash: number | null;
}

export function emptyInventoryDraft(): InventoryDraft {
  return { base: {}, names: {}, cash: null };
}

// Bestand eines Elements aus Stammdaten -- dieselbe Rechnung wie in der Kachel «Kennzahlen»,
// hier nur auf dem Entwurf statt auf dem gespeicherten Stand.
function wealthOf(category: string, d: PhaseData): number {
  if (category === "OTHER_ASSET") return num(d.startValue);
  if (category === "PENSION_FUND" || category === "PILLAR_3A") return num(d.currentValue);
  if (category === "REAL_ESTATE") return num(d.purchasePrice) - num(d.mortgage);
  if (category === "OTHER_DEBT") return -num(d.startValue);
  return 0;
}

// Die Stammdaten-Felder einer Kategorie. Eigene Komponente, weil sie an ZWEI Orten
// erscheinen: im Assistenten-Schritt 1 (als Liste) und in der Matrix-Spalte «Start» (einzeln).
// Zwei Implementierungen derselben Felder liefen garantiert auseinander.
export function BaseFields({
  category,
  values,
  set,
}: {
  category: string;
  values: PhaseData;
  set: (patch: Partial<PhaseData>) => void;
}) {
  const kind = KINDS.find((k) => k.category === category);
  return <>{kind?.baseFields(values, set)}</>;
}

export function InventoryFields({
  plan,
  draft,
  setDraft,
  onChanged,
}: {
  plan: PlanInput;
  draft: InventoryDraft;
  setDraft: (fn: (d: InventoryDraft) => InventoryDraft) => void;
  onChanged: () => void;
}) {
  const scopes: Scope[] =
    plan.householdType === "COUPLE" ? ["HOUSEHOLD", "PERSON_A", "PERSON_B"] : ["PERSON_A"];
  const [page, setPage] = useState(0);
  const scope = scopes[page];
  const cash = draft.cash ?? Math.round(plan.initialCash || 0);

  // Live-Summe aus dem ENTWURF: Sie soll sich beim Tippen bewegen, nicht erst beim Speichern.
  const today = plan.elements.reduce(
    (sum, e) => sum + wealthOf(e.category, draft.base[e.id] ?? e.baseData ?? {}),
    cash
  );

  return (
    <div className="flex flex-col gap-4">
      {/* Cash steht ausserhalb der Reiter: Es ist kein Element und gehört keiner Person --
          es ist der Topf, aus dem alles fliesst und in den alles zurückfliesst. */}
      <div className="rounded-xl border border-border bg-surface-2 p-3">
        <MoneyField
          label="Cash heute (Konto- und Sparguthaben)"
          help="Alles, was sofort verfügbar ist. Aus diesem Topf zahlt FPT die Ausgaben; was du sparst und nicht zuteilst, bleibt hier liegen."
          value={cash}
          onChange={(x) => setDraft((d) => ({ ...d, cash: x }))}
        />
      </div>

      {scopes.length > 1 && (
        <div className="flex gap-1 rounded-lg border border-border bg-surface-2 p-1 text-xs">
          {scopes.map((sc, i) => (
            <button
              key={sc}
              type="button"
              onClick={() => setPage(i)}
              className={`flex-1 rounded-md px-2 py-1 font-medium ${
                page === i ? "bg-accent text-accent-fg" : "text-muted hover:bg-surface"
              }`}
            >
              {sc === "HOUSEHOLD" ? "Gemeinsam" : ownerLabel(plan.persons, sc)}
            </button>
          ))}
        </div>
      )}

      <ScopeElements plan={plan} scope={scope} draft={draft} setDraft={setDraft} onChanged={onChanged} />

      {/* Die einzige Zahl, die schon vor jeder Zeitplanung etwas aussagt -- und die erste
          Rueckmeldung auf die Bestandsaufnahme. */}
      <div className="sticky bottom-0 flex items-baseline justify-between gap-3 border-t border-border bg-surface px-1 pt-3">
        <span className="text-xs font-semibold uppercase tracking-wide text-faint">Vermögen heute</span>
        <span className="text-lg font-semibold tabular-nums text-fg">{formatChf(today)}</span>
      </div>
    </div>
  );
}

function ScopeElements({
  plan,
  scope,
  draft,
  setDraft,
  onChanged,
}: {
  plan: PlanInput;
  scope: Scope;
  draft: InventoryDraft;
  setDraft: (fn: (d: InventoryDraft) => InventoryDraft) => void;
  onChanged: () => void;
}) {
  const [busy, setBusy] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);
  const kinds = KINDS.filter((k) => (scope === "HOUSEHOLD" ? !k.personOnly : true));
  const mine = plan.elements.filter((e) => (e.ownerRole ?? "HOUSEHOLD") === scope);

  // Das Element entsteht SOFORT -- es braucht eine Id, an der die Werte haengen. Nur die
  // Zahlen werden bis zum Abschluss des Schritts zurueckgehalten.
  async function add(kind: Kind) {
    setBusy(kind.key);
    setError(null);
    try {
      const suffix =
        plan.householdType === "COUPLE" && scope !== "HOUSEHOLD" ? ` ${ownerLabel(plan.persons, scope)}` : "";
      await api.post(`/api/scenarios/${plan.id}/elements`, {
        category: kind.category,
        name: `${kind.defaultName}${suffix}`,
        ownerRole: scope,
      });
      onChanged();
    } catch (e) {
      setError(e instanceof Error ? e.message : "Anlegen fehlgeschlagen.");
    } finally {
      setBusy(null);
    }
  }

  return (
    <div className="flex flex-col gap-3">
      {/* Der Knopf traegt den Kategorienamen, die Erklaerung steht darunter -- so lernt man
          beim ersten Kontakt die Vokabel, die auch die Matrix verwendet. */}
      <div className="grid gap-1.5 sm:grid-cols-2 lg:grid-cols-3">
        {kinds.map((k) => (
          <button
            key={k.key}
            type="button"
            disabled={busy === k.key}
            onClick={() => add(k)}
            className="flex items-start gap-1.5 rounded-lg border border-dashed border-border px-2.5 py-1.5 text-left transition-colors hover:border-accent hover:bg-accent-soft/20"
          >
            <Plus className="mt-0.5 h-3.5 w-3.5 shrink-0 text-accent" />
            <span className="min-w-0">
              <span className="block text-xs font-semibold text-fg">{k.label}</span>
              <span className="block text-[11px] leading-snug text-muted">{k.hint}</span>
            </span>
          </button>
        ))}
      </div>

      {mine.length === 0 ? (
        <p className="rounded-lg border border-dashed border-border bg-surface-2 p-3 text-sm text-muted">
          Noch nichts erfasst. Wähle oben, was zutrifft – du kannst jederzeit weitere Positionen ergänzen.
        </p>
      ) : (
        <div className="flex flex-col gap-2">
          {mine.map((el) => (
            <BaseDataCard
              key={el.id}
              plan={plan}
              elementId={el.id}
              draft={draft}
              setDraft={setDraft}
              onChanged={onChanged}
            />
          ))}
        </div>
      )}
      {error && <p className="text-sm text-danger">{error}</p>}
    </div>
  );
}

function BaseDataCard({
  plan,
  elementId,
  draft,
  setDraft,
  onChanged,
}: {
  plan: PlanInput;
  elementId: string;
  draft: InventoryDraft;
  setDraft: (fn: (d: InventoryDraft) => InventoryDraft) => void;
  onChanged: () => void;
}) {
  const el = plan.elements.find((x) => x.id === elementId)!;
  const kind = KINDS.find((k) => k.category === el.category);
  const values = draft.base[el.id] ?? el.baseData ?? {};
  const name = draft.names[el.id] ?? el.name;

  const set = (patch: Partial<PhaseData>) =>
    setDraft((d) => ({ ...d, base: { ...d.base, [el.id]: { ...(d.base[el.id] ?? el.baseData ?? {}), ...patch } } }));

  async function remove() {
    await api.delete(`/api/elements/${el.id}`);
    setDraft((d) => {
      const base = { ...d.base };
      const names = { ...d.names };
      delete base[el.id];
      delete names[el.id];
      return { ...d, base, names };
    });
    onChanged();
  }

  return (
    <div className="rounded-xl border border-border p-3">
      <div className="mb-2 flex items-center gap-2">
        <span className="text-xs font-semibold uppercase tracking-wide text-faint">
          {CATEGORY_LABELS[el.category]}
        </span>
        <button
          type="button"
          onClick={remove}
          className="ml-auto rounded p-1 text-faint hover:bg-danger-soft hover:text-danger"
          aria-label="Entfernen"
        >
          <Trash2 className="h-3.5 w-3.5" />
        </button>
      </div>
      <div className="grid gap-3 sm:grid-cols-2">
        <div className="sm:col-span-2">
          <TextField
            label="Bezeichnung"
            value={name}
            onChange={(v) => setDraft((d) => ({ ...d, names: { ...d.names, [el.id]: v } }))}
          />
        </div>
        {kind ? (
          kind.baseFields(values, set)
        ) : (
          // Die AHV ist die einzige Kategorie ohne Bestand: Es gibt kein Guthaben zum
          // Nachschlagen, nur eine Beitragskarriere. Eine leere Karte sähe nach einem Fehler
          // aus -- deshalb steht hier, warum nichts zu tun ist.
          <p className="sm:col-span-2 rounded-lg bg-surface-2 px-3 py-2 text-xs text-muted">
            Hier gibt es nichts zu erfassen. Die AHV-Rente entsteht aus deiner Beitragskarriere – FPT leitet sie
            aus den Einkommen dieses Plans ab. Beim Übergang in die Pension kannst du sie prüfen und um
            Beitragslücken vor Planbeginn ergänzen.
          </p>
        )}
      </div>
    </div>
  );
}

// Schreibt den gesammelten Entwurf. Wird vom Schritt-Dialog beim Abschliessen aufgerufen --
// es gibt bewusst keinen Speichern-Knopf je Karte mehr.
export async function saveInventoryDraft(plan: PlanInput, draft: InventoryDraft): Promise<void> {
  for (const el of plan.elements) {
    const nextName = draft.names[el.id]?.trim();
    if (nextName && nextName !== el.name) {
      await api.patch(`/api/elements/${el.id}`, { name: nextName });
    }
    const base = draft.base[el.id];
    if (base) await api.put(`/api/elements/${el.id}/base`, base);
  }
  // Cash hängt am Szenario, nicht an einem Element -- eigener Endpunkt.
  if (draft.cash !== null && draft.cash !== plan.initialCash) {
    await api.patch(`/api/scenarios/${plan.id}`, { initialCash: draft.cash });
  }

  // Die AHV entsteht am Schluss von selbst -- je Person eine.
  //
  // Sie hat als einzige Kategorie KEINEN Bestand: Es gibt kein Guthaben, das man nachschlagen
  // könnte, nur eine Beitragskarriere. Ein Plus-Knopf mit einer leeren Karte darunter wäre
  // deshalb sinnlos gewesen. Weglassen ist aber keine Option: In der Schweiz hat jede Person
  // eine AHV, und ohne das Element rechnet der Plan ab der Pensionierung mit einer Rente von 0.
  //
  // IDEMPOTENT: Wer die Bestandsaufnahme später korrigiert und erneut abschliesst, bekommt
  // kein zweites Element -- geprüft wird je Person, nicht global.
  for (const person of plan.persons) {
    const exists = plan.elements.some((e) => e.category === "AHV" && e.ownerRole === person.role);
    if (exists) continue;
    const name = person.name?.trim() ? `AHV ${person.name.trim()}` : "AHV";
    await api.post(`/api/scenarios/${plan.id}/elements`, {
      category: "AHV",
      name,
      ownerRole: person.role,
    });
  }
}



// --- Der Dialog drumherum -------------------------------------------------------------------
//
// Gespeichert wird EINMAL, beim Abschliessen. Ein Speichern-Knopf je Element hätte bedeutet,
// dass ein Reiter-Wechsel die getippten Zahlen verwirft -- deshalb liegt der Entwurf hier
// oben und nicht in den einzelnen Karten.
export function InventoryDialog({
  plan,
  onClose,
  onChanged,
  onSaved,
}: {
  plan: PlanInput;
  onClose: () => void;
  // Der Plan hat sich geaendert (Element angelegt oder geloescht) -- neu laden, aber den
  // Dialog OFFEN lassen. Getrennt von onSaved, denn das schliesst ihn.
  onChanged: () => void;
  onSaved: () => void;
}) {
  const [draft, setDraft] = useState<InventoryDraft>(emptyInventoryDraft);
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const confirm = useConfirm();

  const dirty =
    Object.keys(draft.base).length > 0 ||
    Object.keys(draft.names).length > 0 ||
    (draft.cash !== null && draft.cash !== plan.initialCash);

  async function closeGuarded() {
    if (!dirty) return onClose();
    const ok = await confirm({
      title: "Eingaben verwerfen?",
      message:
        "Du hast Angaben erfasst, die noch nicht gespeichert sind. Schliesst du jetzt, gehen sie verloren. " +
        "Mit «Bestandsaufnahme abschliessen» werden sie übernommen.",
      confirmLabel: "Verwerfen",
      danger: true,
    });
    if (ok) onClose();
  }

  async function save() {
    setSaving(true);
    setError(null);
    try {
      await saveInventoryDraft(plan, draft);
      setDraft(emptyInventoryDraft());
      onSaved();
    } catch (e) {
      setError(e instanceof Error ? e.message : "Speichern fehlgeschlagen.");
      setSaving(false);
    }
  }

  return (
    <Modal
      title="Bestandsaufnahme"
      subtitle="Alles, was du heute hast – Einkommen, Ausgaben, Guthaben, Immobilien, Schulden"
      onClose={closeGuarded}
      xwide
    >
      <div className="flex flex-col gap-4">
        <div className="rounded-xl border border-border bg-surface-2 p-3 text-xs leading-relaxed text-muted">
          Hier stehen nur Zahlen, die du <strong className="text-fg">nachschlagen</strong> kannst. Renditen,
          Lohnentwicklung und Teuerung kommen später – sie sind Annahmen, und eine Annahme gilt immer nur für
          einen bestimmten Zeitraum. Du triffst sie in den Lebensphasen.
        </div>

        <InventoryFields
          plan={plan}
          draft={draft}
          setDraft={(fn) => setDraft((d) => fn(d))}
          onChanged={onChanged}
        />

        {error && <p className="text-sm text-danger">{error}</p>}
        <div className="flex items-center justify-between border-t border-border pt-3">
          <Button variant="ghost" onClick={closeGuarded}>
            Abbrechen
          </Button>
          <Button disabled={saving} onClick={save}>
            <Check className="h-4 w-4" /> {saving ? "Wird gespeichert…" : "Bestandsaufnahme abschliessen"}
          </Button>
        </div>
      </div>
    </Modal>
  );
}
