<script lang="ts">
  import { onMount } from "svelte";
  import { browser } from "$app/environment";
  import { env } from "$env/dynamic/public";
  import { marked } from "$lib/markdown-safe";
  import { getBlockLayoutClasses } from "$lib/block-layout";
  import type { StellingnahmeGeneratorBlockData } from "$lib/block-types";
  import type { TextFragment, WindArea } from "$lib/windkarte";
  import "$lib/iconify-offline";
  import Icon from "@iconify/svelte";

  let {
    block,
    class: className = "",
  }: {
    block: StellingnahmeGeneratorBlockData;
    class?: string;
  } = $props();

  const layoutClasses = $derived(getBlockLayoutClasses(block.layout));

  // ── Resolved server data ─────────────────────────────────────────────────────
  const windArea = $derived(
    typeof block.windArea === "object" && block.windArea !== null
      ? (block.windArea as WindArea & { stellungnahme_kriterien?: TextFragment[] })
      : null,
  );

  const kriterien = $derived(
    (windArea?.stellungnahme_kriterien ?? []).filter(
      (k): k is TextFragment => typeof k === "object" && k !== null && "_slug" in k,
    ),
  );

  const allgemeineArgumente = $derived(
    (block.allgemeineArgumente ?? []) as TextFragment[],
  );

  // Tag used to fetch allgemeineArgumente — exclude from grouping categories
  const fetchTagSlug = $derived(
    typeof block.allgemeineArgumenteTag === "object" && block.allgemeineArgumenteTag !== null
      ? (block.allgemeineArgumenteTag as { _slug: string })._slug
      : (block.allgemeineArgumenteTag as string | undefined) ?? "",
  );

  // Deduplicate: remove allgemeine fragments already covered by ortskonkrete (id, fallback _slug)
  const ortskonkreteIds = $derived(new Set(kriterien.map((k) => k.id ?? k._slug)));
  const allgemeineDeduped = $derived(
    allgemeineArgumente.filter((f) => !ortskonkreteIds.has(f.id ?? f._slug)),
  );

  // Group allgemeine by first non-fetch tag; use tag.name as label
  type Group = { slug: string; label: string; items: TextFragment[] };
  const allgemeineGruppen = $derived.by((): Group[] => {
    const map = new Map<string, Group>();
    for (const f of allgemeineDeduped) {
      const relevantTags = (f.tags ?? []).filter((t) => {
        const slug = typeof t === "string" ? t : t._slug;
        return slug !== fetchTagSlug;
      });
      let groupSlug = "__weitere";
      let groupLabel = "Weitere Argumente";
      if (relevantTags.length > 0) {
        const first = relevantTags[0];
        if (typeof first === "string") {
          groupSlug = first;
          // Slug → label: strip "tag-" prefix, replace hyphens with spaces, capitalize
          groupLabel = first
            .replace(/^tag-?/, "")
            .replace(/-/g, " ")
            .replace(/^\w/, (c) => c.toUpperCase());
        } else {
          groupSlug = first._slug;
          groupLabel =
            first.name ??
            first._slug
              .replace(/^tag-?/, "")
              .replace(/-/g, " ")
              .replace(/^\w/, (c) => c.toUpperCase());
        }
      }
      if (!map.has(groupSlug)) {
        map.set(groupSlug, { slug: groupSlug, label: groupLabel, items: [] });
      }
      map.get(groupSlug)!.items.push(f);
    }
    return Array.from(map.values());
  });

  // ── localStorage ────────────────────────────────────────────────────────────
  const storageKey = `stellungnahme:${block._slug ?? block.id ?? "default"}`;
  const historyKey = `${storageKey}:history`;

  type HistoryEntry = { text: string; date: string; argCount: number };
  let outputHistory = $state<HistoryEntry[]>([]);
  let historyExpanded = $state(false);
  let mounted = $state(false);
  let hadSavedState = $state(false);

  function saveState() {
    try {
      localStorage.setItem(storageKey, JSON.stringify({
        selectedSlugs: Array.from(selectedSlugs),
        persoenlicheEingabe,
        absenderName,
        absenderAnschrift,
        absenderOrt,
        argNotes,
        openingOverride,
        closingOverride,
      }));
    } catch {}
  }

  $effect(() => {
    void [selectedSlugs, persoenlicheEingabe, absenderName, absenderAnschrift, absenderOrt, argNotes, openingOverride, closingOverride];
    if (mounted) saveState();
  });

  // ── Step state ───────────────────────────────────────────────────────────────
  // 0 Gebietskontext | 1 Ortskonkret | 2 Allgemein | 3 Betroffenheit | 4 Ausgabe
  type Step = 0 | 1 | 2 | 3 | 4;
  let step = $state<Step>(0);

  let selectedSlugs = $state<Set<string>>(new Set());
  let expandedGroups = $state<Set<string>>(new Set()); // empty = all collapsed
  let expandedItems = $state<Set<string>>(new Set()); // per-item text expand

  function toggleItem(slug: string) {
    const next = new Set(expandedItems);
    if (next.has(slug)) next.delete(slug);
    else next.add(slug);
    expandedItems = next;
  }

  const mode = "fertig";
  let persoenlicheEingabe = $state("");
  let absenderName = $state("");
  let absenderAnschrift = $state("");
  let absenderOrt = $state("");
  let showOutput = $state(false);

  // Per-argument notes (appear in output after bullet points)
  let argNotes = $state<Record<string, string>>({});
  function setArgNote(slug: string, value: string) {
    argNotes = { ...argNotes, [slug]: value };
  }

  // Editable opening/closing — null = use reactive default
  const defaultOpening = $derived(
    `ich erhebe Einwendung gegen die Ausweisung des Windenergie-Vorranggebiets ${gebietsBez} im 2. Entwurf des Regionalplans Südwestthüringen.`,
  );
  const defaultClosing = "Ich fordere die Regionalplanung auf, das Vorranggebiet aus dem Regionalplan zu streichen oder zumindest einer erneuten, umfassenden Überprüfung zu unterziehen.";
  let openingOverride = $state<string | null>(null);
  let closingOverride = $state<string | null>(null);
  const effectiveOpening = $derived(openingOverride ?? defaultOpening);
  const effectiveClosing = $derived(closingOverride ?? defaultClosing);


  function toggleSlug(slug: string) {
    const next = new Set(selectedSlugs);
    const nextExpanded = new Set(expandedItems);
    if (next.has(slug)) {
      next.delete(slug);
      nextExpanded.delete(slug);
    } else {
      next.add(slug);
      nextExpanded.add(slug);
    }
    selectedSlugs = next;
    expandedItems = nextExpanded;
  }

  function toggleGroup(slug: string) {
    const next = new Set(expandedGroups);
    if (next.has(slug)) next.delete(slug);
    else next.add(slug);
    expandedGroups = next;
  }

  function toggleGroupSelection(group: Group) {
    const slugs = group.items.map((f) => f._slug);
    const allSelected = slugs.every((s) => selectedSlugs.has(s));
    const next = new Set(selectedSlugs);
    for (const s of slugs) {
      if (allSelected) next.delete(s);
      else next.add(s);
    }
    selectedSlugs = next;
    // Expand on select, collapse on deselect
    const nextGroups = new Set(expandedGroups);
    if (allSelected) nextGroups.delete(group.slug);
    else nextGroups.add(group.slug);
    expandedGroups = nextGroups;
  }

  // Combined selection for output — ortskonkrete first, then allgemeine
  const selectedFragments = $derived([
    ...kriterien.filter((k) => selectedSlugs.has(k._slug)),
    ...allgemeineDeduped.filter((k) => selectedSlugs.has(k._slug)),
  ]);

  const ortskonkreteSelectedCount = $derived(
    kriterien.filter((k) => selectedSlugs.has(k._slug)).length,
  );
  const allgemeineSelectedCount = $derived(
    allgemeineDeduped.filter((k) => selectedSlugs.has(k._slug)).length,
  );

  // ── Output ───────────────────────────────────────────────────────────────────
  const RECIPIENT = `Regionale Planungsgemeinschaft Südwestthüringen
Regionale Planungsstelle
Karl-Liebknecht-Straße 4
98527 Suhl`;

  const gebietsBez = $derived(
    windArea
      ? `${windArea.gebiets_nr}${windArea.bezeichnung ? " – " + windArea.bezeichnung : ""}`
      : "",
  );

  const mailtoLink = $derived.by(() => {
    if (!block.recipientEmail || !outputText) return "";
    const subject = `Einwendung Regionalplan Südwestthüringen – Vorranggebiet ${gebietsBez}`;
    return `mailto:${block.recipientEmail}?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(outputText)}`;
  });

  function buildText(): string {
    const heute = new Date().toLocaleDateString("de-DE", { day: "2-digit", month: "2-digit", year: "numeric" });
    const sender = [absenderName.trim(), absenderAnschrift.trim(), absenderOrt.trim()]
      .filter(Boolean)
      .join("\n");
    const betreff = `Einwendung zum Entwurf des Regionalplans Südwestthüringen (2. Entwurf)\nWindenergie-Vorranggebiet ${gebietsBez}`;
    const closing = absenderName.trim()
      ? `Mit freundlichen Grüßen\n\n${absenderName.trim()}`
      : "Mit freundlichen Grüßen";
    const disclaimer = `${"=".repeat(64)}
!! ENTWURF – KEIN FERTIGER BRIEF !!
Stichpunkte müssen vor dem Einreichen in eigene, ausformulierte
Sätze überführt werden. Text individuell anpassen.
${"=".repeat(64)}`;
    let body = `${effectiveOpening}\n\n`;
    for (const f of selectedFragments) {
      if (f.title) body += `${f.title}\n\n`;
      if (f.bulletPoints?.length) {
        for (const bp of f.bulletPoints) body += `- ${bp}\n`;
        body += "\n";
      } else if (f.text) {
        body += `${stripMd(f.text)}\n\n`;
      }
      const note = argNotes[f._slug]?.trim();
      if (note) body += `Anmerkung: ${note}\n\n`;
    }
    if (persoenlicheEingabe.trim())
      body += `Persönliche Betroffenheit\n\n${persoenlicheEingabe.trim()}\n\n`;
    body += `${effectiveClosing}\n\n${closing}`;

    return [disclaimer, "", sender, "", heute, "", "An:", RECIPIENT, "", "Betreff: " + betreff.split("\n")[0], betreff.split("\n")[1] ?? "", "", "Sehr geehrte Damen und Herren,", "", body.trimEnd()]
      .join("\n")
      .replace(/\n{3,}/g, "\n\n");
  }

  let sectionEl: HTMLElement | undefined;

  function goTo(target: Step) {
    // Skip step 1 when no ortskonkrete arguments exist
    let s = target;
    if (s === 1 && kriterien.length === 0) {
      s = (target > step ? 2 : 0) as Step;
    }
    step = s;
    setTimeout(() => sectionEl?.scrollIntoView({ behavior: "smooth", block: "start" }), 0);
  }

  let outputText = $state("");
  let copyFeedback = $state("");

  function generateOutput() {
    outputText = buildText();
    showOutput = true;
    const entry: HistoryEntry = {
      text: outputText,
      date: new Date().toLocaleString("de-DE", { dateStyle: "short", timeStyle: "short" }),
      argCount: selectedFragments.length,
    };
    outputHistory = [entry, ...outputHistory.filter((h) => h.text !== outputText)].slice(0, 5);
    try { localStorage.setItem(historyKey, JSON.stringify(outputHistory)); } catch {}
  }

  function clearHistory() {
    outputHistory = [];
    try { localStorage.removeItem(historyKey); } catch {}
  }

  function resetAll() {
    selectedSlugs = new Set();
    expandedItems = new Set();
    expandedGroups = new Set();
    argNotes = {};
    openingOverride = null;
    closingOverride = null;
    persoenlicheEingabe = "";
    absenderName = "";
    absenderAnschrift = "";
    absenderOrt = "";
    showOutput = false;
    outputText = "";
    hadSavedState = false;
    try { localStorage.removeItem(storageKey); } catch {}
  }

  function downloadText() {
    const blob = new Blob([outputText], { type: "text/plain;charset=utf-8" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = `einwendung-${windArea?.gebiets_nr ?? "stellungnahme"}.txt`;
    a.click();
    URL.revokeObjectURL(url);
  }

  async function copyText() {
    try {
      await navigator.clipboard.writeText(outputText);
      copyFeedback = "Kopiert!";
      setTimeout(() => (copyFeedback = ""), 2000);
    } catch {
      copyFeedback = "Kopieren fehlgeschlagen";
    }
  }

  function printText() {
    const w = window.open("", "_blank");
    if (!w) return;
    w.document.write(
      `<html><head><title>Stellungnahme</title><style>
        body { font-family: serif; font-size: 13pt; line-height: 1.6; margin: 2cm; white-space: pre-wrap; }
        @media print { body { margin: 2cm; } }
      </style></head><body>${outputText.replace(/</g, "&lt;").replace(/>/g, "&gt;")}</body></html>`,
    );
    w.document.close();
    w.print();
  }

  function md(text: string | undefined): string {
    if (!text) return "";
    return marked.parse(text) as string;
  }

  function stripMd(text: string): string {
    return text
      .replace(/\*\*(.+?)\*\*/g, "$1")
      .replace(/\*(.+?)\*/g, "$1")
      .replace(/^#{1,6}\s+/gm, "")
      .replace(/\[(.+?)\]\(.+?\)/g, "$1")
      .trim();
  }

  const STEP_LABELS = ["Gebiet", "Ortskonkret", "Allgemein", "Betroffenheit", "Ausgabe"] as const;
  const TOTAL_STEPS = 5;

  // ── Deadline ─────────────────────────────────────────────────────────────────
  const deadlineDate = $derived(block.deadline ? new Date(block.deadline) : null);
  const deadlineDays = $derived.by(() => {
    if (!deadlineDate) return null;
    const now = new Date(); now.setHours(0, 0, 0, 0);
    const d = new Date(deadlineDate); d.setHours(0, 0, 0, 0);
    return Math.ceil((d.getTime() - now.getTime()) / 86_400_000);
  });
  const deadlineFormatted = $derived(
    deadlineDate?.toLocaleDateString("de-DE", { day: "2-digit", month: "long", year: "numeric" }) ?? "",
  );

  // ── Mini-map ─────────────────────────────────────────────────────────────────
  const CMS_BASE = (env.PUBLIC_CMS_URL || "http://localhost:3000").replace(/\/$/, "");

  let mapAreaData = $state<WindArea[]>([]);
  let mapReady = $state(false);
  let mapActive = $state(false);

  const MapComponent = browser
    ? import("$lib/components/WindkarteMap.svelte").then((m) => m.default)
    : null;

  // ── Hash navigation ──────────────────────────────────────────────────────────
  function parseStepHash(hash: string): Step | null {
    const m = hash.match(/^#step-(\d+)$/);
    if (!m) return null;
    const n = (parseInt(m[1], 10) - 1) as Step;
    return n >= 0 && n < TOTAL_STEPS ? n : null;
  }

  // Sync step → hash (only when hash doesn't already match)
  $effect(() => {
    if (typeof window === "undefined") return;
    const target = `#step-${step + 1}`;
    if (location.hash !== target) location.hash = target;
  });

  onMount(() => {
    // Restore persisted state
    try {
      const saved = localStorage.getItem(storageKey);
      if (saved) {
        const s = JSON.parse(saved);
        if (Array.isArray(s.selectedSlugs)) selectedSlugs = new Set(s.selectedSlugs);
        if (typeof s.persoenlicheEingabe === "string") persoenlicheEingabe = s.persoenlicheEingabe;
        if (typeof s.absenderName === "string") absenderName = s.absenderName;
        if (typeof s.absenderAnschrift === "string") absenderAnschrift = s.absenderAnschrift;
        if (typeof s.absenderOrt === "string") absenderOrt = s.absenderOrt;
        if (s.argNotes && typeof s.argNotes === "object") argNotes = s.argNotes;
        if (typeof s.openingOverride === "string") openingOverride = s.openingOverride;
        if (typeof s.closingOverride === "string") closingOverride = s.closingOverride;
        if ((s.selectedSlugs?.length ?? 0) > 0 || s.absenderName || s.persoenlicheEingabe) {
          hadSavedState = true;
        }
      }
      const savedHistory = localStorage.getItem(historyKey);
      if (savedHistory) outputHistory = JSON.parse(savedHistory);
    } catch {}
    mounted = true;

    const parsed = parseStepHash(location.hash);
    if (parsed !== null) step = parsed;

    const onHashChange = () => {
      const p = parseStepHash(location.hash);
      if (p !== null && p !== step) step = p;
    };
    window.addEventListener("hashchange", onHashChange);

    // Fetch wind_area with geometry for mini-map
    if (windArea?._slug) {
      fetch(`${CMS_BASE}/api/content/wind_area/${windArea._slug}`, {
        signal: AbortSignal.timeout(6_000),
      })
        .then((r) => (r.ok ? r.json() : null))
        .then((data) => {
          if (data) mapAreaData = [data];
        })
        .catch(() => {})
        .finally(() => { mapReady = true; });
    } else {
      mapReady = true;
    }

    return () => window.removeEventListener("hashchange", onHashChange);
  });
</script>

<section bind:this={sectionEl} class="{layoutClasses} {className}">
  <!-- Deadline banner -->
  {#if deadlineDays !== null && deadlineDays >= 0}
    {@const urgent = deadlineDays <= 3}
    {@const soon = deadlineDays <= 7}
    <div class="mb-4 flex items-center gap-3 rounded-lg border px-4 py-3 text-sm font-medium
      {urgent ? 'border-red-300 bg-red-50 text-red-800' : soon ? 'border-orange-300 bg-orange-50 text-orange-800' : 'border-gelb-300 bg-gelb-50 text-gelb-800'}">
      <Icon icon="mdi:clock-alert-outline" class="size-5 shrink-0" />
      <span>
        Einwendungsfrist: <strong>{deadlineFormatted}</strong>
        {#if deadlineDays === 0}— <strong>heute letzter Tag!</strong>
        {:else if deadlineDays === 1}— <strong>morgen letzter Tag!</strong>
        {:else}— noch {deadlineDays} Tage
        {/if}
      </span>
    </div>
  {/if}

  <!-- Privacy notice -->
  <div class="mb-4 flex items-start gap-2 rounded-lg border border-himmel-200 bg-himmel-50 px-4 py-3 text-sm text-himmel-800">
    <svg class="mt-0.5 h-4 w-4 shrink-0" viewBox="0 0 20 20" fill="currentColor">
      <path fill-rule="evenodd" d="M10 1a4.5 4.5 0 00-4.5 4.5V9H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-.5V5.5A4.5 4.5 0 0010 1zm3 8V5.5a3 3 0 10-6 0V9h6z" clip-rule="evenodd" />
    </svg>
    <span><strong>Ihre Daten bleiben auf Ihrem Gerät.</strong> Name, Anschrift und alle Eingaben werden nicht an Server übertragen.</span>
  </div>

  <!-- Fortsetzen-Banner -->
  {#if hadSavedState && step === 0}
    <div class="mb-6 flex flex-wrap items-center justify-between gap-3 rounded-lg border border-wald-300 bg-wald-50 px-4 py-3 text-sm">
      <span class="text-wald-800"><Icon icon="mdi:content-save-outline" class="mr-1 inline size-4" />Letzte Sitzung wiederhergestellt.</span>
      <div class="flex gap-2">
        {#if outputHistory.length > 0}
          <button class="rounded-md bg-wald-700 px-3 py-1.5 text-xs font-semibold text-white hover:bg-wald-800" onclick={() => goTo(4)}>Zur Ausgabe →</button>
        {:else if selectedSlugs.size > 0}
          <button class="rounded-md bg-wald-700 px-3 py-1.5 text-xs font-semibold text-white hover:bg-wald-800" onclick={() => goTo(3)}>Fortsetzen →</button>
        {/if}
        <button class="rounded-md border border-stein-300 px-3 py-1.5 text-xs text-stein-600 hover:bg-stein-50" onclick={resetAll}>Neu starten</button>
      </div>
    </div>
  {/if}

  {#if block.headline}
    <h2 class="mb-2 text-2xl font-bold text-wald-900">{block.headline}</h2>
  {/if}
  {#if block.intro}
    <div class="prose prose-wald mb-6 max-w-none text-stein-700">{@html md(block.intro)}</div>
  {/if}

  <!-- Step indicator -->
  <div class="mb-2 flex items-center gap-1 text-xs font-medium">
    {#each Array.from({ length: TOTAL_STEPS }, (_, i) => i) as s}
      <button
        class="flex h-7 w-7 items-center justify-center rounded-full border transition-colors
          {s === step
            ? 'border-wald-700 bg-wald-700 text-white'
            : s < step
              ? 'border-wald-400 bg-wald-100 text-wald-700'
              : 'border-stein-300 bg-white text-stein-400'}"
        onclick={() => { if (s <= step) goTo(s as Step); }}
        disabled={s > step}
        aria-current={s === step ? "step" : undefined}
        title={STEP_LABELS[s]}
      >{s + 1}</button>
      {#if s < TOTAL_STEPS - 1}
        <div class="h-px flex-1 {s < step ? 'bg-wald-400' : 'bg-stein-200'}"></div>
      {/if}
    {/each}
  </div>
  <p class="mb-6 text-right text-xs text-stein-400">Schritt {step + 1} von {TOTAL_STEPS} – {STEP_LABELS[step]}</p>

  <!-- ── Step 0: Gebietskontext ─────────────────────────────────────────────── -->
  {#if step === 0}
    <div>
      <h3 class="mb-4 text-lg font-semibold text-wald-800">Schritt 1 – Ihr Vorranggebiet</h3>

      {#if windArea}
        <div class="mb-6 rounded-xl border border-wald-200 bg-wald-50 p-5">
          <div class="mb-2 text-xs font-medium uppercase tracking-wide text-wald-600">Vorranggebiet</div>
          <div class="text-xl font-bold text-wald-900">{windArea.gebiets_nr}</div>
          {#if windArea.bezeichnung}
            <div class="mt-0.5 text-base text-wald-700">{windArea.bezeichnung}</div>
          {/if}
          <dl class="mt-4 grid grid-cols-2 gap-x-6 gap-y-2 text-sm sm:grid-cols-3">
            {#if windArea.gemeinden?.length}
              <div class="col-span-full">
                <dt class="text-stein-500">Gemeinden</dt>
                <dd class="font-medium text-stein-800">{windArea.gemeinden.join(", ")}</dd>
              </div>
            {/if}
            {#if windArea.flaeche_ha}
              <div>
                <dt class="text-stein-500">Fläche</dt>
                <dd class="font-medium text-stein-800">{windArea.flaeche_ha.toLocaleString("de-DE")} ha</dd>
              </div>
            {/if}
            {#if windArea.anlagen_geplant}
              <div>
                <dt class="text-stein-500">Anlagen geplant</dt>
                <dd class="font-medium text-stein-800">{windArea.anlagen_geplant}</dd>
              </div>
            {/if}
            {#if windArea.hoehe_max_m}
              <div>
                <dt class="text-stein-500">Max. Höhe</dt>
                <dd class="font-medium text-stein-800">{windArea.hoehe_max_m} m</dd>
              </div>
            {/if}
            {#if windArea.investor}
              <div>
                <dt class="text-stein-500">Investor</dt>
                <dd class="font-medium text-stein-800">{windArea.investor}</dd>
              </div>
            {/if}
            {#if windArea.status}
              <div>
                <dt class="text-stein-500">Status</dt>
                <dd class="font-medium text-stein-800 capitalize">{windArea.status.replace(/_/g, " ")}</dd>
              </div>
            {/if}
          </dl>
          {#if windArea.notizen}
            <div class="mt-4 border-t border-wald-200 pt-3 text-sm text-stein-700">{@html md(windArea.notizen)}</div>
          {/if}
        </div>

        <!-- Mini-map -->
        {#if browser && MapComponent && mapReady && mapAreaData.length > 0}
          <div class="relative mb-6 overflow-hidden rounded-xl border border-stein-200 shadow-sm" style="height:320px">
            {#await MapComponent then Map}
              <Map
                areas={mapAreaData}
                initialGebietsNr={windArea.gebiets_nr}
                hiddenStatuses={[]}
                hiddenRings={["2km","5km"]}
                fitBoundsMaxZoom={13}
                onselect={() => {}}
              />
            {/await}
            {#if !mapActive}
              <button
                type="button"
                onclick={() => (mapActive = true)}
                class="absolute inset-0 z-[500] flex cursor-pointer flex-col items-center justify-center gap-2 bg-black/10 backdrop-blur-[1px]"
                aria-label="Karte aktivieren"
              >
                <span class="rounded-lg bg-white/90 px-4 py-2 text-sm font-medium text-stein-700 shadow">
                  Klicken zum Aktivieren der Karte
                </span>
              </button>
            {/if}
          </div>
        {:else if mapReady && mapAreaData.length === 0}
          <!-- no geometry available, skip silently -->
        {:else if !mapReady}
          <div class="mb-6 flex h-40 items-center justify-center rounded-xl border border-stein-200 bg-stein-50 text-sm text-stein-400">
            Karte wird geladen …
          </div>
        {/if}

      {:else}
        <div class="mb-6 rounded-xl border border-erde-200 bg-erde-50 p-4 text-sm text-erde-700">
          Kein Vorranggebiet konfiguriert.
        </div>
      {/if}

      <p class="mb-6 text-sm text-stein-600">
        Dieser Assistent hilft Ihnen, eine individuelle Einwendung für den
        <strong>2. Entwurf des Regionalplans Südwestthüringen</strong> zu verfassen.
        Sie wählen zuerst ortskonkrete Argumente für Ihr Gebiet, dann allgemeine Einwände.
      </p>
      <div class="flex flex-wrap items-center gap-3">
        <button
          class="rounded-lg bg-wald-700 px-6 py-2.5 font-semibold text-white transition hover:bg-wald-800 disabled:opacity-40"
          disabled={!windArea}
          onclick={() => goTo(1)}
        >Weiter zu den Argumenten →</button>
        {#if selectedSlugs.size > 0 || absenderName}
          <button class="text-xs text-stein-400 hover:text-stein-600" onclick={resetAll}>Neu starten</button>
        {/if}
      </div>
    </div>

  <!-- ── Step 1: Ortskonkrete Argumente ───────────────────────────────────── -->
  {:else if step === 1}
    <div>
      <h3 class="mb-1 text-lg font-semibold text-wald-800">Schritt 2 – Ortskonkrete Argumente</h3>
      <p class="mb-5 text-sm text-stein-600">
        Diese Argumente beziehen sich direkt auf das Gebiet <strong>{windArea?.gebiets_nr ?? ""}</strong>.
        Wählen Sie die Punkte, die auf Ihre Situation zutreffen.
      </p>

      {#if kriterien.length > 0}
        <div class="mb-6 space-y-2">
          {#each kriterien as k}
            <div class="rounded-lg border transition-colors {selectedSlugs.has(k._slug) ? 'border-wald-400 bg-wald-50' : 'border-stein-200 bg-white'}">
              <div class="flex items-start gap-3 p-3">
                <input
                  type="checkbox"
                  class="mt-0.5 h-4 w-4 shrink-0 rounded accent-wald-700"
                  checked={selectedSlugs.has(k._slug)}
                  onchange={() => toggleSlug(k._slug)}
                />
                <div class="min-w-0 flex-1">
                  <div class="flex items-center justify-between gap-2">
                    <span class="cursor-pointer font-medium text-stein-800" onclick={() => toggleSlug(k._slug)}>{k.title ?? k._slug.replace(/_/g, " ")}</span>
                    {#if k.text}
                      <button
                        class="shrink-0 text-wald-500 hover:text-wald-800"
                        onclick={() => toggleItem(k._slug)}
                        aria-label={expandedItems.has(k._slug) ? "Einklappen" : "Ausklappen"}
                      ><Icon icon={expandedItems.has(k._slug) ? "mdi:chevron-up" : "mdi:chevron-down"} class="size-4" /></button>
                    {/if}
                  </div>
                </div>
              </div>
              {#if expandedItems.has(k._slug)}
                <div class="border-t border-stein-100 px-3 pb-3 pt-2 space-y-2">
                  {#if k.text}
                    <div class="prose prose-sm prose-stein max-w-none text-sm text-stein-700">{@html md(k.text)}</div>
                  {/if}
                  <textarea
                    class="w-full rounded border border-stein-200 px-2 py-1.5 text-xs text-stein-700 placeholder:text-stein-400 focus:border-wald-400 focus:outline-none focus:ring-1 focus:ring-wald-200 resize-none"
                    rows="2"
                    placeholder="Persönliche Notiz zu diesem Punkt (erscheint im Dokument) …"
                    value={argNotes[k._slug] ?? ""}
                    oninput={(e) => setArgNote(k._slug, (e.target as HTMLTextAreaElement).value)}
                  ></textarea>
                </div>
              {/if}
            </div>
          {/each}
        </div>
      {:else}
        <div class="mb-6 rounded-xl border border-erde-200 bg-erde-50 p-4 text-sm text-erde-700">
          Für dieses Gebiet sind noch keine ortskonkreten Argumente hinterlegt.
        </div>
      {/if}

      <div class="flex items-center gap-3">
        <button class="rounded-lg border border-stein-300 px-4 py-2 text-sm text-stein-600 hover:bg-stein-50" onclick={() => goTo(0)}>← Zurück</button>
        <button class="rounded-lg bg-wald-700 px-6 py-2.5 font-semibold text-white transition hover:bg-wald-800" onclick={() => goTo(2)}>
          Weiter{ortskonkreteSelectedCount > 0 ? ` (${ortskonkreteSelectedCount} gewählt)` : ""} →
        </button>
      </div>
    </div>

  <!-- ── Step 2: Allgemeine Argumente ─────────────────────────────────────── -->
  {:else if step === 2}
    <div>
      <h3 class="mb-1 text-lg font-semibold text-wald-800">Schritt 3 – Grundsätzliche Einwände</h3>
      <p class="mb-1 text-sm text-stein-600">
        Welche allgemeinen Argumente teilen Sie? Diese gelten unabhängig vom konkreten Standort.
      </p>
      {#if ortskonkreteSelectedCount > 0}
        <p class="mb-4 text-xs text-stein-400">
          Bereits aus Schritt 2 übernommen: {ortskonkreteSelectedCount} ortskonkrete{ortskonkreteSelectedCount !== 1 ? "s Argument" : " Argumente"}.
        </p>
      {:else}
        <p class="mb-4 text-xs text-stein-400">Aus Schritt 2: keine ortskonkreten Argumente ausgewählt.</p>
      {/if}

      {#if allgemeineGruppen.length > 0}
        <div class="mb-6 space-y-2">
          {#each allgemeineGruppen as group}
            {@const groupSelectedCount = group.items.filter((f) => selectedSlugs.has(f._slug)).length}
            {@const allSelected = groupSelectedCount === group.items.length}
            {@const isExpanded = expandedGroups.has(group.slug)}
            <div class="rounded-lg border {groupSelectedCount > 0 ? 'border-stein-400' : 'border-stein-200'} overflow-hidden">
              <!-- Group header -->
              <div class="flex items-center gap-2 bg-stein-50 px-3 py-2.5">
                <button
                  class="flex flex-1 items-center gap-2 text-left"
                  onclick={() => toggleGroup(group.slug)}
                  aria-expanded={isExpanded}
                >
                  <Icon icon={isExpanded ? "mdi:chevron-down" : "mdi:chevron-right"} class="size-4 shrink-0 text-stein-400" />
                  <span class="font-medium text-stein-800 text-sm">{group.label}</span>
                  <span class="ml-auto text-xs text-stein-500">
                    {groupSelectedCount > 0 ? `${groupSelectedCount}/` : ""}{group.items.length}
                  </span>
                </button>
                <button
                  class="rounded px-2 py-0.5 text-xs font-medium transition
                    {allSelected ? 'bg-stein-200 text-stein-700 hover:bg-stein-300' : 'bg-wald-100 text-wald-700 hover:bg-wald-200'}"
                  onclick={() => toggleGroupSelection(group)}
                  title={allSelected ? "Alle abwählen" : "Alle wählen"}
                >
                  {allSelected ? "Alle ab" : "Alle"}
                </button>
              </div>

              <!-- Group items -->
              {#if isExpanded}
                <div class="divide-y divide-stein-100">
                  {#each group.items as f}
                    <div class="transition-colors {selectedSlugs.has(f._slug) ? 'bg-wald-50' : 'bg-white'}">
                      <div class="flex items-start gap-3 px-3 py-2.5">
                        <input
                          type="checkbox"
                          class="mt-0.5 h-4 w-4 shrink-0 rounded accent-wald-700"
                          checked={selectedSlugs.has(f._slug)}
                          onchange={() => toggleSlug(f._slug)}
                        />
                        <div class="min-w-0 flex-1">
                          <div class="flex items-center justify-between gap-2">
                            <span class="cursor-pointer text-sm font-medium text-stein-800" onclick={() => toggleSlug(f._slug)}>{f.title ?? f._slug.replace(/_/g, " ")}</span>
                            {#if f.text}
                              <button
                                class="shrink-0 text-wald-500 hover:text-wald-800"
                                onclick={() => toggleItem(f._slug)}
                                aria-label={expandedItems.has(f._slug) ? "Einklappen" : "Ausklappen"}
                              ><Icon icon={expandedItems.has(f._slug) ? "mdi:chevron-up" : "mdi:chevron-down"} class="size-4" /></button>
                            {/if}
                          </div>
                        </div>
                      </div>
                      {#if expandedItems.has(f._slug)}
                        <div class="border-t border-stein-100 px-3 pb-3 pt-2 space-y-2">
                          {#if f.text}
                            <div class="prose prose-sm prose-stein max-w-none text-sm text-stein-700">{@html md(f.text)}</div>
                          {/if}
                          <textarea
                            class="w-full rounded border border-stein-200 px-2 py-1.5 text-xs text-stein-700 placeholder:text-stein-400 focus:border-wald-400 focus:outline-none focus:ring-1 focus:ring-wald-200 resize-none"
                            rows="2"
                            placeholder="Persönliche Notiz zu diesem Punkt (erscheint im Dokument) …"
                            value={argNotes[f._slug] ?? ""}
                            oninput={(e) => setArgNote(f._slug, (e.target as HTMLTextAreaElement).value)}
                          ></textarea>
                        </div>
                      {/if}
                    </div>
                  {/each}
                </div>
              {/if}
            </div>
          {/each}
        </div>
      {:else}
        <div class="mb-6 rounded-xl border border-erde-200 bg-erde-50 p-4 text-sm text-erde-700">
          Keine allgemeinen Argumente hinterlegt.
        </div>
      {/if}

      <div class="flex items-center gap-3">
        <button class="rounded-lg border border-stein-300 px-4 py-2 text-sm text-stein-600 hover:bg-stein-50" onclick={() => goTo(1)}>← Zurück</button>
        <button
          class="rounded-lg bg-wald-700 px-6 py-2.5 font-semibold text-white transition hover:bg-wald-800 disabled:opacity-40"
          disabled={selectedFragments.length === 0}
          onclick={() => goTo(3)}
        >
          Weiter ({selectedFragments.length} Argument{selectedFragments.length !== 1 ? "e" : ""}) →
        </button>
      </div>
    </div>

  <!-- ── Step 3: Persönliche Betroffenheit ─────────────────────────────────── -->
  {:else if step === 3}
    <div>
      <h3 class="mb-1 text-lg font-semibold text-wald-800">Schritt 4 – Persönliche Betroffenheit</h3>
      <p class="mb-2 text-sm text-stein-600">
        Beschreiben Sie kurz, wie Sie persönlich betroffen sind.
        <strong>Wichtig:</strong> Individuelle Betroffenheit stärkt Ihre Einwendung erheblich
        und macht sie von anderen unterscheidbar.
      </p>
      <p class="mb-4 text-xs text-stein-400">
        Beispiel: Ich wohne 800 m vom geplanten Standort entfernt und bin Eigentümer von …
      </p>
      <textarea
        class="w-full rounded-lg border border-stein-300 px-4 py-3 text-sm text-stein-800 focus:border-wald-500 focus:outline-none focus:ring-2 focus:ring-wald-200"
        rows="6"
        placeholder="Meine Betroffenheit: …"
        bind:value={persoenlicheEingabe}
      ></textarea>
      <p class="mt-1 text-xs text-stein-400">Bleibt auf Ihrem Gerät. Wird nicht übertragen.</p>
      <div class="mt-5 flex items-center gap-3">
        <button class="rounded-lg border border-stein-300 px-4 py-2 text-sm text-stein-600 hover:bg-stein-50" onclick={() => goTo(2)}>← Zurück</button>
        <button class="rounded-lg bg-wald-700 px-6 py-2.5 font-semibold text-white transition hover:bg-wald-800" onclick={() => goTo(4)}>Weiter →</button>
      </div>
    </div>

  <!-- ── Step 4: Absender + Ausgabe ────────────────────────────────────────── -->
  {:else if step === 4}
    <div>
      <h3 class="mb-1 text-lg font-semibold text-wald-800">Schritt 5 – Absender & Ausgabe</h3>
      <p class="mb-4 text-sm text-stein-600">Ihre Daten werden nur lokal zur Texterstellung genutzt.</p>

      <div class="mb-5 grid gap-3 sm:grid-cols-2">
        <div>
          <label class="mb-1 block text-xs font-medium text-stein-600" for="absender-name">Vor- und Nachname</label>
          <input id="absender-name" type="text" class="w-full rounded-lg border border-stein-300 px-3 py-2 text-sm focus:border-wald-500 focus:outline-none focus:ring-2 focus:ring-wald-200" placeholder="Max Mustermann" bind:value={absenderName} />
        </div>
        <div>
          <label class="mb-1 block text-xs font-medium text-stein-600" for="absender-anschrift">Straße und Hausnummer</label>
          <input id="absender-anschrift" type="text" class="w-full rounded-lg border border-stein-300 px-3 py-2 text-sm focus:border-wald-500 focus:outline-none focus:ring-2 focus:ring-wald-200" placeholder="Hauptstr. 1" bind:value={absenderAnschrift} />
        </div>
        <div class="sm:col-span-2">
          <label class="mb-1 block text-xs font-medium text-stein-600" for="absender-ort">PLZ und Ort</label>
          <input id="absender-ort" type="text" class="w-full rounded-lg border border-stein-300 px-3 py-2 text-sm focus:border-wald-500 focus:outline-none focus:ring-2 focus:ring-wald-200" placeholder="98529 Suhl" bind:value={absenderOrt} />
        </div>
      </div>

      <div class="mb-5 rounded-lg border border-stein-200 bg-stein-50 p-3 text-xs text-stein-600">
        <div class="mb-1 font-semibold text-stein-700">Einzureichen bei:</div>
        <div class="whitespace-pre">{RECIPIENT}</div>
      </div>

      <!-- Einleitung & Abschluss anpassen -->
      <div class="mb-4 space-y-2">
        <details class="rounded-lg border border-stein-200 overflow-hidden">
          <summary class="flex cursor-pointer items-center justify-between bg-stein-50 px-4 py-2.5 text-sm font-medium text-stein-700 hover:bg-stein-100 list-none">
            <span>Einleitung anpassen</span>
            <Icon icon="mdi:chevron-down" class="size-4 text-stein-400" />
          </summary>
          <div class="border-t border-stein-100 px-4 py-3">
            <textarea
              class="w-full rounded border border-stein-200 px-3 py-2 text-sm text-stein-800 focus:border-wald-400 focus:outline-none focus:ring-1 focus:ring-wald-200 resize-y"
              rows="3"
              value={effectiveOpening}
              oninput={(e) => (openingOverride = (e.target as HTMLTextAreaElement).value)}
            ></textarea>
            {#if openingOverride !== null}
              <button class="mt-1 text-xs text-stein-400 hover:text-stein-600" onclick={() => (openingOverride = null)}>Zurücksetzen</button>
            {/if}
          </div>
        </details>
        <details class="rounded-lg border border-stein-200 overflow-hidden">
          <summary class="flex cursor-pointer items-center justify-between bg-stein-50 px-4 py-2.5 text-sm font-medium text-stein-700 hover:bg-stein-100 list-none">
            <span>Abschluss anpassen</span>
            <Icon icon="mdi:chevron-down" class="size-4 text-stein-400" />
          </summary>
          <div class="border-t border-stein-100 px-4 py-3">
            <textarea
              class="w-full rounded border border-stein-200 px-3 py-2 text-sm text-stein-800 focus:border-wald-400 focus:outline-none focus:ring-1 focus:ring-wald-200 resize-y"
              rows="3"
              value={effectiveClosing}
              oninput={(e) => (closingOverride = (e.target as HTMLTextAreaElement).value)}
            ></textarea>
            {#if closingOverride !== null}
              <button class="mt-1 text-xs text-stein-400 hover:text-stein-600" onclick={() => (closingOverride = null)}>Zurücksetzen</button>
            {/if}
          </div>
        </details>
      </div>

      <div class="mb-2 flex gap-3">
        <button class="rounded-lg border border-stein-300 px-4 py-2 text-sm text-stein-600 hover:bg-stein-50" onclick={() => goTo(3)}>← Zurück</button>
        <button
          class="btn-wiggle rounded-lg bg-wald-700 px-6 py-2.5 font-semibold text-white transition hover:bg-wald-800 disabled:opacity-40"
          disabled={!absenderName.trim()}
          onclick={generateOutput}
        >Text erstellen</button>
      </div>
      {#if !absenderName.trim()}
        <p class="mb-4 text-xs text-erde-600">Bitte Namen eintragen, um den Text zu erstellen.</p>
      {:else}
        <div class="mb-4"></div>
      {/if}

      {#if showOutput}
        <div class="rounded-xl border border-wald-300 bg-white shadow-sm">
          <div class="flex items-center justify-between border-b border-wald-200 px-4 py-3">
            <span class="text-sm font-semibold text-wald-800">Ihre Einwendung</span>
            <div class="flex gap-2">
              <button class="rounded-md border border-stein-300 px-3 py-1.5 text-xs font-medium text-stein-700 hover:bg-stein-50" onclick={copyText}>{copyFeedback || "Kopieren"}</button>
              <button class="rounded-md border border-stein-300 px-3 py-1.5 text-xs font-medium text-stein-700 hover:bg-stein-50" onclick={downloadText}>Herunterladen</button>
              <button class="rounded-md border border-stein-300 px-3 py-1.5 text-xs font-medium text-stein-700 hover:bg-stein-50" onclick={printText}>Drucken</button>
              {#if mailtoLink}
                <a href={mailtoLink} class="rounded-md border border-wald-400 bg-wald-50 px-3 py-1.5 text-xs font-medium text-wald-700 hover:bg-wald-100">Per E-Mail senden</a>
              {/if}
            </div>
          </div>
          <div class="overflow-x-auto whitespace-pre-wrap break-words px-5 py-4 font-sans text-sm leading-relaxed text-stein-800">{outputText}</div>
        </div>
        <div class="mt-4 rounded-lg border border-himmel-200 bg-himmel-50 px-4 py-3 text-sm text-himmel-800">
          <strong>Hinweis:</strong> Bitte passen Sie den Text vor dem Einreichen individuell an.
          Einwendungen mit persönlichen Formulierungen sind wirksamer als identische Kopien.
        </div>
      {/if}

      <!-- History -->
      {#if outputHistory.length > 0}
        <div class="mt-6">
          <button
            class="flex w-full items-center justify-between rounded-lg border border-stein-200 bg-stein-50 px-4 py-2.5 text-sm font-medium text-stein-700 hover:bg-stein-100"
            onclick={() => (historyExpanded = !historyExpanded)}
          >
            <span>Frühere Versionen ({outputHistory.length})</span>
            <Icon icon={historyExpanded ? "mdi:chevron-up" : "mdi:chevron-down"} class="size-4" />
          </button>

          {#if historyExpanded}
            <div class="mt-2 space-y-2">
              {#each outputHistory as entry, i}
                <div class="rounded-lg border border-stein-200 bg-white">
                  <div class="flex items-center justify-between border-b border-stein-100 px-4 py-2 text-xs text-stein-500">
                    <span>{entry.date} · {entry.argCount} Argument{entry.argCount !== 1 ? "e" : ""}</span>
                    <button
                      class="text-wald-600 hover:text-wald-800"
                      onclick={() => { outputText = entry.text; showOutput = true; }}
                    >Wiederherstellen</button>
                  </div>
                  <div class="max-h-40 overflow-y-auto whitespace-pre-wrap break-words px-4 py-3 font-sans text-xs text-stein-600">{entry.text.slice(0, 400)}{entry.text.length > 400 ? " …" : ""}</div>
                </div>
              {/each}
              <button
                class="text-xs text-stein-400 hover:text-stein-600"
                onclick={clearHistory}
              >Verlauf löschen</button>
            </div>
          {/if}
        </div>
      {/if}
    </div>
  {/if}
</section>

<style>
  @keyframes wiggle {
    0%, 100% { transform: rotate(0deg); }
    20% { transform: rotate(-2deg); }
    40% { transform: rotate(2deg); }
    60% { transform: rotate(-1.5deg); }
    80% { transform: rotate(1.5deg); }
  }
  .btn-wiggle {
    animation: wiggle 2.4s ease-in-out infinite;
  }
  .btn-wiggle:hover {
    animation: none;
  }
</style>
