"use client";

import { useState, useEffect, useCallback, useMemo, useRef } from "react";
import {
  Loader2,
  FileDown,
  CheckCircle2,
  XCircle,
  Wifi,
  MapPin,
  Sparkles,
  RefreshCw,
  Database,
  HardDrive,
  Clock,
  ArrowDownToLine,
  AlertTriangle,
} from "lucide-react";
import { Button } from "@/shared/components/ui/button";
import { Badge } from "@/shared/components/ui/badge";
import { Card, CardContent } from "@/shared/components/ui/card";
import { cn } from "@/shared/lib/utils";
import {
  LAYER_CATALOG,
} from "../../services/eterra-layers";
import type {
  SessionStatus,
  SyncRunInfo,
  ExportProgress,
} from "../parcel-sync-types";
import { relativeTime } from "../parcel-sync-types";

/* ------------------------------------------------------------------ */
/*  Props                                                              */
/* ------------------------------------------------------------------ */

export type ExportTabProps = {
  siruta: string;
  workspacePk: number | null;
  sirutaValid: boolean;
  session: SessionStatus;
  syncLocalCounts: Record<string, number>;
  syncRuns: SyncRunInfo[];
  syncingSiruta: string;
  exporting: boolean;
  setExporting: (v: boolean) => void;
  onSyncRefresh: () => void;
  onDbRefresh: () => void;
};

/* ------------------------------------------------------------------ */
/*  No-geom scan result type                                           */
/* ------------------------------------------------------------------ */

type NoGeomScanResult = {
  totalImmovables: number;
  withGeometry: number;
  remoteGisCount: number;
  remoteCladiriCount: number;
  noGeomCount: number;
  matchedByRef: number;
  matchedById: number;
  qualityBreakdown: {
    withCadRef: number;
    withPaperCad: number;
    withPaperLb: number;
    withLandbook: number;
    withArea: number;
    withActiveStatus: number;
    useful: number;
    empty: number;
  };
  localDbTotal: number;
  localDbWithGeom: number;
  localDbNoGeom: number;
  localDbEnriched: number;
  localDbEnrichedComplete: number;
  localSyncFresh: boolean;
  scannedAt: string;
};

/* ------------------------------------------------------------------ */
/*  Component                                                          */
/* ------------------------------------------------------------------ */

export function ExportTab({
  siruta,
  workspacePk,
  sirutaValid,
  session,
  syncLocalCounts,
  syncRuns,
  syncingSiruta,
  exporting,
  setExporting,
  onSyncRefresh,
  onDbRefresh,
}: ExportTabProps) {
  /* ── Export state ──────────────────────────────────────────── */
  const [exportJobId, setExportJobId] = useState<string | null>(null);
  const [exportProgress, setExportProgress] = useState<ExportProgress | null>(
    null,
  );
  const [phaseTrail, setPhaseTrail] = useState<string[]>([]);
  const pollingRef = useRef<ReturnType<typeof setInterval> | null>(null);

  /* ── No-geometry state ────────────────────────────────────── */
  const [includeNoGeom, setIncludeNoGeom] = useState(false);
  const [noGeomScanning, setNoGeomScanning] = useState(false);
  const [noGeomScan, setNoGeomScan] = useState<NoGeomScanResult | null>(null);
  const [noGeomScanSiruta, setNoGeomScanSiruta] = useState("");

  /* ── Background sync state ────────────────────────────────── */
  const [bgJobId, setBgJobId] = useState<string | null>(null);
  const [bgProgress, setBgProgress] = useState<ExportProgress | null>(null);
  const [bgPhaseTrail, setBgPhaseTrail] = useState<string[]>([]);
  const bgPollingRef = useRef<ReturnType<typeof setInterval> | null>(null);
  const [downloadingFromDb, setDownloadingFromDb] = useState(false);

  /* ══════════════════════════════════════════════════════════ */
  /*  Derived data                                              */
  /* ══════════════════════════════════════════════════════════ */

  const dbLayersSummary = useMemo(() => {
    if (!sirutaValid || syncingSiruta !== siruta) return [];
    return LAYER_CATALOG.filter((l) => (syncLocalCounts[l.id] ?? 0) > 0).map(
      (l) => {
        const count = syncLocalCounts[l.id] ?? 0;
        const lastRun = syncRuns.find(
          (r) => r.layerId === l.id && r.status === "done",
        );
        const lastSynced = lastRun?.completedAt
          ? new Date(lastRun.completedAt)
          : null;
        const ageMs = lastSynced ? Date.now() - lastSynced.getTime() : null;
        const isFresh = ageMs !== null ? ageMs < 168 * 60 * 60 * 1000 : false;
        return { ...l, count, lastSynced, isFresh };
      },
    );
  }, [sirutaValid, syncingSiruta, siruta, syncLocalCounts, syncRuns]);

  const dbTotalFeatures = dbLayersSummary.reduce((sum, l) => sum + l.count, 0);

  const progressPct =
    exportProgress?.total && exportProgress.total > 0
      ? Math.round((exportProgress.downloaded / exportProgress.total) * 100)
      : 0;

  /* ══════════════════════════════════════════════════════════ */
  /*  Progress polling                                          */
  /* ══════════════════════════════════════════════════════════ */

  const startPolling = useCallback((jid: string) => {
    if (pollingRef.current) clearInterval(pollingRef.current);
    pollingRef.current = setInterval(async () => {
      try {
        const res = await fetch(
          `/api/eterra/progress?jobId=${encodeURIComponent(jid)}`,
        );
        const data = (await res.json()) as ExportProgress;
        setExportProgress(data);
        if (data.phase) {
          setPhaseTrail((prev) => {
            if (prev[prev.length - 1] === data.phase) return prev;
            return [...prev, data.phase!];
          });
        }
        if (data.status === "done" || data.status === "error") {
          if (pollingRef.current) {
            clearInterval(pollingRef.current);
            pollingRef.current = null;
          }
        }
      } catch {
        /* ignore polling errors */
      }
    }, 1000);
  }, []);

  useEffect(() => {
    return () => {
      if (pollingRef.current) clearInterval(pollingRef.current);
    };
  }, []);

  /* ══════════════════════════════════════════════════════════ */
  /*  Export bundle (base / magic)                              */
  /* ══════════════════════════════════════════════════════════ */

  const handleExportBundle = useCallback(
    async (mode: "base" | "magic") => {
      if (!siruta || exporting) return;
      const jobId = crypto.randomUUID();
      setExportJobId(jobId);
      setExportProgress(null);
      setPhaseTrail([]);
      setExporting(true);

      startPolling(jobId);

      try {
        const res = await fetch("/api/eterra/export-bundle", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            siruta,
            jobId,
            mode,
            includeNoGeometry: includeNoGeom,
          }),
        });

        if (!res.ok) {
          const err = (await res.json().catch(() => ({}))) as {
            error?: string;
          };
          throw new Error(err.error ?? `HTTP ${res.status}`);
        }

        const blob = await res.blob();
        const cd = res.headers.get("Content-Disposition") ?? "";
        const match = /filename="?([^"]+)"?/.exec(cd);
        const filename =
          match?.[1] ??
          (mode === "magic"
            ? `eterra_uat_${siruta}_magic.zip`
            : `eterra_uat_${siruta}_terenuri_cladiri.zip`);

        const url = URL.createObjectURL(blob);
        const a = document.createElement("a");
        a.href = url;
        a.download = filename;
        document.body.appendChild(a);
        a.click();
        a.remove();
        URL.revokeObjectURL(url);

        // Mark progress as done after successful download
        setExportProgress((prev) =>
          prev
            ? {
                ...prev,
                status: "done",
                phase: "Finalizat",
                downloaded: prev.total ?? 100,
                total: prev.total ?? 100,
                message: `Descărcare completă — ${filename}`,
                note: undefined,
              }
            : null,
        );
      } catch (error) {
        const msg = error instanceof Error ? error.message : "Eroare export";
        setExportProgress((prev) =>
          prev
            ? { ...prev, status: "error", message: msg }
            : {
                jobId,
                downloaded: 0,
                status: "error",
                message: msg,
              },
        );
      }

      if (pollingRef.current) {
        clearInterval(pollingRef.current);
        pollingRef.current = null;
      }
      setExporting(false);
      // Refresh sync status — data was synced to DB
      onSyncRefresh();
    },
    [siruta, exporting, startPolling, includeNoGeom, setExporting, onSyncRefresh],
  );

  /* ══════════════════════════════════════════════════════════ */
  /*  No-geometry scan                                          */
  /* ══════════════════════════════════════════════════════════ */

  const handleNoGeomScan = useCallback(
    async (targetSiruta?: string) => {
      const s = targetSiruta ?? siruta;
      if (!s) return;
      setNoGeomScanning(true);
      setNoGeomScan(null);
      setNoGeomScanSiruta(s);
      const emptyQuality = {
        withCadRef: 0,
        withPaperCad: 0,
        withPaperLb: 0,
        withLandbook: 0,
        withArea: 0,
        withActiveStatus: 0,
        useful: 0,
        empty: 0,
      };
      const emptyResult: NoGeomScanResult = {
        totalImmovables: 0,
        withGeometry: 0,
        remoteGisCount: 0,
        remoteCladiriCount: 0,
        noGeomCount: 0,
        matchedByRef: 0,
        matchedById: 0,
        qualityBreakdown: emptyQuality,
        localDbTotal: 0,
        localDbWithGeom: 0,
        localDbNoGeom: 0,
        localDbEnriched: 0,
        localDbEnrichedComplete: 0,
        localSyncFresh: false,
        scannedAt: "",
      };
      try {
        // 2min timeout — scan is informational, should not block the page
        const scanAbort = new AbortController();
        const scanTimer = setTimeout(() => scanAbort.abort(), 120_000);
        const res = await fetch("/api/eterra/no-geom-scan", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            siruta: s,
            workspacePk: workspacePk ?? undefined,
          }),
          signal: scanAbort.signal,
        });
        clearTimeout(scanTimer);
        const data = (await res.json()) as Record<string, unknown>;
        if (data.error) {
          console.warn("[no-geom-scan]", data.error);
          setNoGeomScan(emptyResult);
        } else {
          const qb = (data.qualityBreakdown ?? {}) as Record<string, unknown>;
          setNoGeomScan({
            totalImmovables: Number(data.totalImmovables ?? 0),
            withGeometry: Number(data.withGeometry ?? 0),
            remoteGisCount: Number(data.remoteGisCount ?? 0),
            remoteCladiriCount: Number(data.remoteCladiriCount ?? 0),
            noGeomCount: Number(data.noGeomCount ?? 0),
            matchedByRef: Number(data.matchedByRef ?? 0),
            matchedById: Number(data.matchedById ?? 0),
            qualityBreakdown: {
              withCadRef: Number(qb.withCadRef ?? 0),
              withPaperCad: Number(qb.withPaperCad ?? 0),
              withPaperLb: Number(qb.withPaperLb ?? 0),
              withLandbook: Number(qb.withLandbook ?? 0),
              withArea: Number(qb.withArea ?? 0),
              withActiveStatus: Number(qb.withActiveStatus ?? 0),
              useful: Number(qb.useful ?? 0),
              empty: Number(qb.empty ?? 0),
            },
            localDbTotal: Number(data.localDbTotal ?? 0),
            localDbWithGeom: Number(data.localDbWithGeom ?? 0),
            localDbNoGeom: Number(data.localDbNoGeom ?? 0),
            localDbEnriched: Number(data.localDbEnriched ?? 0),
            localDbEnrichedComplete: Number(data.localDbEnrichedComplete ?? 0),
            localSyncFresh: Boolean(data.localSyncFresh),
            scannedAt: String(data.scannedAt ?? new Date().toISOString()),
          });
        }
      } catch (err) {
        // Distinguish timeout from other errors for the user
        const isTimeout =
          err instanceof DOMException && err.name === "AbortError";
        if (isTimeout) {
          console.warn(
            "[no-geom-scan] Timeout after 2 min — server eTerra lent",
          );
        }
        setNoGeomScan({
          ...emptyResult,
          scannedAt: isTimeout ? "timeout" : "",
        });
      }
      setNoGeomScanning(false);
    },
    [siruta, workspacePk],
  );

  // Auto-scan for no-geometry parcels when UAT is selected + connected
  const noGeomAutoScanRef = useRef("");
  useEffect(() => {
    if (!siruta || !session.connected) return;
    // Don't re-scan if we already scanned (or are scanning) this siruta
    if (noGeomAutoScanRef.current === siruta) return;
    noGeomAutoScanRef.current = siruta;
    void handleNoGeomScan(siruta);
  }, [siruta, session.connected, handleNoGeomScan]);

  /* ══════════════════════════════════════════════════════════ */
  /*  Background sync polling                                   */
  /* ══════════════════════════════════════════════════════════ */

  const startBgPolling = useCallback(
    (jid: string) => {
      if (bgPollingRef.current) clearInterval(bgPollingRef.current);
      bgPollingRef.current = setInterval(async () => {
        try {
          const res = await fetch(
            `/api/eterra/progress?jobId=${encodeURIComponent(jid)}`,
          );
          const data = (await res.json()) as ExportProgress;
          setBgProgress(data);
          if (data.phase) {
            setBgPhaseTrail((prev) => {
              if (prev[prev.length - 1] === data.phase) return prev;
              return [...prev, data.phase!];
            });
          }
          if (data.status === "done" || data.status === "error") {
            if (bgPollingRef.current) {
              clearInterval(bgPollingRef.current);
              bgPollingRef.current = null;
            }
            // Clean localStorage marker
            try {
              localStorage.removeItem("parcel-sync:bg-job");
            } catch {
              /* */
            }
            // Refresh sync status and DB summary
            onSyncRefresh();
            onDbRefresh();
          }
        } catch {
          /* ignore polling errors */
        }
      }, 1500);
    },
    [onSyncRefresh, onDbRefresh],
  );

  // Cleanup bg polling on unmount
  useEffect(() => {
    return () => {
      if (bgPollingRef.current) clearInterval(bgPollingRef.current);
    };
  }, []);

  // Recover background job from localStorage on mount
  useEffect(() => {
    try {
      const raw = localStorage.getItem("parcel-sync:bg-job");
      if (!raw) return;
      const saved = JSON.parse(raw) as {
        jobId: string;
        siruta: string;
        startedAt: string;
      };
      // Ignore jobs older than 8 hours
      const age = Date.now() - new Date(saved.startedAt).getTime();
      if (age > 8 * 60 * 60 * 1000) {
        localStorage.removeItem("parcel-sync:bg-job");
        return;
      }
      // Check if job is still running
      void (async () => {
        try {
          const res = await fetch(
            `/api/eterra/progress?jobId=${encodeURIComponent(saved.jobId)}`,
          );
          const data = (await res.json()) as ExportProgress;
          if (data.status === "running") {
            setBgJobId(saved.jobId);
            setBgProgress(data);
            if (data.phase) setBgPhaseTrail([data.phase]);
            startBgPolling(saved.jobId);
          } else if (data.status === "done") {
            setBgJobId(saved.jobId);
            setBgProgress(data);
            if (data.phase) setBgPhaseTrail(["Sincronizare completă"]);
            localStorage.removeItem("parcel-sync:bg-job");
          } else {
            localStorage.removeItem("parcel-sync:bg-job");
          }
        } catch {
          localStorage.removeItem("parcel-sync:bg-job");
        }
      })();
    } catch {
      /* */
    }
  }, [startBgPolling]);

  /* ══════════════════════════════════════════════════════════ */
  /*  Background sync — fire-and-forget server-side processing  */
  /* ══════════════════════════════════════════════════════════ */

  const handleSyncBackground = useCallback(
    async (mode: "base" | "magic") => {
      if (!siruta || exporting) return;
      try {
        const res = await fetch("/api/eterra/sync-background", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            siruta,
            mode,
            includeNoGeometry: includeNoGeom,
          }),
        });
        const data = (await res.json()) as { jobId?: string; error?: string };
        if (!res.ok || data.error) {
          // Transient error — ignored in the extracted component
          // (parent's syncProgress state is not available here)
          console.warn("[sync-background]", data.error ?? `Eroare ${res.status}`);
          return;
        }
        const jid = data.jobId!;
        setBgJobId(jid);
        setBgProgress({
          jobId: jid,
          downloaded: 0,
          total: 100,
          status: "running",
          phase: "Pornire sincronizare fundal",
        });
        setBgPhaseTrail(["Pornire sincronizare fundal"]);
        // Persist in localStorage so we can recover on page refresh
        try {
          localStorage.setItem(
            "parcel-sync:bg-job",
            JSON.stringify({
              jobId: jid,
              siruta,
              startedAt: new Date().toISOString(),
            }),
          );
        } catch {
          /* */
        }
        startBgPolling(jid);
      } catch (error) {
        const msg = error instanceof Error ? error.message : "Eroare rețea";
        console.warn("[sync-background]", msg);
      }
    },
    [siruta, exporting, includeNoGeom, startBgPolling],
  );

  /* ══════════════════════════════════════════════════════════ */
  /*  Download from DB                                          */
  /* ══════════════════════════════════════════════════════════ */

  const handleDownloadFromDb = useCallback(
    async (mode: "base" | "magic") => {
      if (!siruta || downloadingFromDb) return;
      setDownloadingFromDb(true);
      try {
        const res = await fetch("/api/eterra/export-local", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ siruta, mode }),
        });
        if (!res.ok) {
          const err = (await res.json().catch(() => ({}))) as {
            error?: string;
          };
          throw new Error(err.error ?? `HTTP ${res.status}`);
        }
        const blob = await res.blob();
        const cd = res.headers.get("Content-Disposition") ?? "";
        const match = /filename="?([^"]+)"?/.exec(cd);
        const filename = match?.[1] ?? `eterra_uat_${siruta}_${mode}_local.zip`;
        const url = URL.createObjectURL(blob);
        const a = document.createElement("a");
        a.href = url;
        a.download = filename;
        document.body.appendChild(a);
        a.click();
        a.remove();
        URL.revokeObjectURL(url);
      } catch (error) {
        const msg =
          error instanceof Error ? error.message : "Eroare descărcare";
        console.warn("[download-from-db]", msg);
      }
      setDownloadingFromDb(false);
    },
    [siruta, downloadingFromDb],
  );

  /* ══════════════════════════════════════════════════════════ */
  /*  Render                                                    */
  /* ══════════════════════════════════════════════════════════ */

  return (
    <div className="space-y-4">
      {/* DB freshness status */}
      {sirutaValid && dbLayersSummary.length > 0 && (
        <Card className="border-dashed">
          <CardContent className="py-3 px-4">
            <div className="flex items-center gap-3 flex-wrap">
              <Database className="h-4 w-4 text-muted-foreground shrink-0" />
              <span className="text-sm text-muted-foreground">
                <span className="font-medium text-foreground">
                  {dbTotalFeatures.toLocaleString("ro-RO")}
                </span>{" "}
                entități în DB din{" "}
                <span className="font-medium text-foreground">
                  {dbLayersSummary.length}
                </span>{" "}
                layere
              </span>
              {(() => {
                const freshCount = dbLayersSummary.filter(
                  (l) => l.isFresh,
                ).length;
                const staleCount = dbLayersSummary.length - freshCount;
                const oldestSync = dbLayersSummary.reduce(
                  (oldest, l) => {
                    if (!l.lastSynced) return oldest;
                    if (!oldest || l.lastSynced < oldest) return l.lastSynced;
                    return oldest;
                  },
                  null as Date | null,
                );
                return (
                  <>
                    {staleCount === 0 ? (
                      <Badge
                        variant="outline"
                        className="text-emerald-600 border-emerald-200 dark:text-emerald-400 dark:border-emerald-800"
                      >
                        <CheckCircle2 className="h-3 w-3 mr-1" />
                        Proaspete
                      </Badge>
                    ) : (
                      <Badge
                        variant="outline"
                        className="text-amber-600 border-amber-200 dark:text-amber-400 dark:border-amber-800"
                      >
                        <Clock className="h-3 w-3 mr-1" />
                        {staleCount} vechi
                      </Badge>
                    )}
                    {oldestSync && (
                      <span className="text-xs text-muted-foreground">
                        Ultima sincronizare: {relativeTime(oldestSync)}
                      </span>
                    )}
                  </>
                );
              })()}
            </div>
          </CardContent>
        </Card>
      )}

      {/* Hero buttons */}
      {sirutaValid && session.connected ? (
        <div className="grid gap-3 sm:grid-cols-2">
          <Button
            size="lg"
            className="h-auto py-4 text-base bg-zinc-900 hover:bg-zinc-800 text-white dark:bg-zinc-100 dark:text-zinc-900 dark:hover:bg-zinc-200"
            disabled={exporting}
            onClick={() => void handleExportBundle("base")}
          >
            {exporting && exportProgress?.phase !== "Detalii parcele" ? (
              <Loader2 className="mr-2 h-5 w-5 animate-spin" />
            ) : (
              <FileDown className="mr-2 h-5 w-5" />
            )}
            <div className="text-left">
              <div className="font-semibold">
                Descarcă Terenuri și Clădiri
              </div>
              <div className="text-xs opacity-70 font-normal">
                Sync + GPKG (din cache dacă e proaspăt)
              </div>
            </div>
          </Button>

          <Button
            size="lg"
            className="h-auto py-4 text-base bg-teal-700 hover:bg-teal-600 text-white dark:bg-teal-600 dark:hover:bg-teal-500"
            disabled={exporting}
            onClick={() => void handleExportBundle("magic")}
          >
            {exporting && exportProgress?.phase === "Detalii parcele" ? (
              <Loader2 className="mr-2 h-5 w-5 animate-spin" />
            ) : (
              <Sparkles className="mr-2 h-5 w-5" />
            )}
            <div className="text-left">
              <div className="font-semibold">Magic</div>
              <div className="text-xs opacity-70 font-normal">
                Sync + îmbogățire (CF, proprietari, adresă) + GPKG + CSV
              </div>
            </div>
          </Button>
        </div>
      ) : (
        <Card>
          <CardContent className="py-12 text-center text-muted-foreground">
            {!session.connected ? (
              <>
                <Wifi className="h-10 w-10 mx-auto mb-3 opacity-30" />
                <p>Conectează-te la eTerra pentru a activa exportul.</p>
              </>
            ) : (
              <>
                <MapPin className="h-10 w-10 mx-auto mb-3 opacity-30" />
                <p>Selectează un UAT pentru a activa exportul.</p>
              </>
            )}
          </CardContent>
        </Card>
      )}

      {/* No-geometry option — shown after auto-scan completes */}
      {sirutaValid &&
        session.connected &&
        (() => {
          const scanDone = noGeomScan !== null && noGeomScanSiruta === siruta;
          const estimatedNoGeom = scanDone
            ? Math.max(
                0,
                noGeomScan.totalImmovables - noGeomScan.remoteGisCount,
              )
            : 0;
          const hasNoGeomParcels = scanDone && estimatedNoGeom > 0;
          const scanning = noGeomScanning;

          // Still scanning
          if (scanning)
            return (
              <Card className="border-amber-200/50 dark:border-amber-800/50">
                <CardContent className="py-3 px-4">
                  <div className="flex items-center gap-2 text-sm text-muted-foreground">
                    <Loader2 className="h-4 w-4 animate-spin text-amber-500" />
                    Se scanează lista de imobile din eTerra… (max 2 min)
                  </div>
                  <p className="text-[11px] text-muted-foreground mt-1 ml-6">
                    Poți folosi butoanele de mai jos fără să aștepți scanarea.
                  </p>
                </CardContent>
              </Card>
            );

          // Scan timed out
          if (scanDone && noGeomScan.scannedAt === "timeout")
            return (
              <Card className="border-amber-200/50 dark:border-amber-800/50">
                <CardContent className="py-3 px-4">
                  <div className="flex items-center gap-2 text-sm text-amber-600 dark:text-amber-400">
                    <Clock className="h-4 w-4 shrink-0" />
                    Scanarea a depășit 2 minute — serverul eTerra e lent.
                  </div>
                  <p className="text-[11px] text-muted-foreground mt-1 ml-6">
                    Poți lansa sincronizarea fundal fără rezultate de scanare.
                    Include no-geom nu va fi disponibil.
                  </p>
                  <Button
                    variant="ghost"
                    size="sm"
                    className="h-6 text-xs mt-1 ml-6"
                    onClick={() => void handleNoGeomScan()}
                  >
                    <RefreshCw className="h-3 w-3 mr-1" />
                    Reîncearcă scanarea
                  </Button>
                </CardContent>
              </Card>
            );

          // Helper: local DB status line
          const staleEnrichment =
            scanDone &&
            noGeomScan.localDbEnriched > 0 &&
            noGeomScan.localDbEnrichedComplete < noGeomScan.localDbEnriched;
          const staleCount = scanDone
            ? noGeomScan.localDbEnriched - noGeomScan.localDbEnrichedComplete
            : 0;

          const localDbLine = scanDone && noGeomScan.localDbTotal > 0 && (
            <div className="space-y-0.5 mt-1">
              <div className="flex items-center gap-1.5 flex-wrap text-[11px] text-muted-foreground">
                <Database className="h-3 w-3 shrink-0" />
                <span>
                  Baza de date locală:{" "}
                  <span className="font-medium text-foreground">
                    {noGeomScan.localDbWithGeom.toLocaleString("ro-RO")}
                  </span>{" "}
                  cu geometrie
                  {noGeomScan.localDbNoGeom > 0 && (
                    <>
                      {" + "}
                      <span className="font-medium text-amber-600 dark:text-amber-400">
                        {noGeomScan.localDbNoGeom.toLocaleString("ro-RO")}
                      </span>{" "}
                      fără geometrie
                    </>
                  )}
                  {noGeomScan.localDbEnriched > 0 && (
                    <>
                      {" · "}
                      <span className="font-medium text-teal-600 dark:text-teal-400">
                        {noGeomScan.localDbEnriched.toLocaleString("ro-RO")}
                      </span>{" "}
                      îmbogățite
                      {staleEnrichment && (
                        <span className="text-orange-600 dark:text-orange-400">
                          {" "}
                          ({staleCount.toLocaleString("ro-RO")} incomplete)
                        </span>
                      )}
                    </>
                  )}
                  {noGeomScan.localSyncFresh && (
                    <span className="text-emerald-600 dark:text-emerald-400 ml-1">
                      (proaspăt)
                    </span>
                  )}
                </span>
              </div>
              {staleEnrichment && (
                <div className="flex items-center gap-1.5 text-[11px] text-orange-600 dark:text-orange-400 ml-[18px]">
                  <AlertTriangle className="h-3 w-3 shrink-0" />
                  <span>
                    {staleCount.toLocaleString("ro-RO")} parcele au îmbogățire
                    veche (lipsă PROPRIETARI_VECHI). Vor fi re-îmbogățite la
                    următorul export Magic.
                  </span>
                </div>
              )}
            </div>
          );

          // Helper: workflow preview (what Magic will do)
          const workflowPreview = scanDone && (
            <div className="mt-2 ml-7 space-y-0.5">
              <p className="text-[11px] font-medium text-muted-foreground">
                La apăsarea Magic, pașii vor fi:
              </p>
              <ol className="text-[11px] text-muted-foreground list-decimal ml-4 space-y-px">
                <li>
                  {"Sync GIS — "}
                  <span
                    className={cn(
                      "font-medium",
                      noGeomScan.localSyncFresh &&
                        noGeomScan.localDbWithGeom > 0
                        ? "text-emerald-600 dark:text-emerald-400"
                        : "text-foreground",
                    )}
                  >
                    {noGeomScan.localSyncFresh &&
                    noGeomScan.localDbWithGeom > 0
                      ? "skip (date proaspete în DB)"
                      : `descarcă ${noGeomScan.remoteGisCount.toLocaleString("ro-RO")} terenuri` +
                        (noGeomScan.remoteCladiriCount > 0
                          ? ` + ${noGeomScan.remoteCladiriCount.toLocaleString("ro-RO")} clădiri`
                          : "")}
                  </span>
                </li>
                {includeNoGeom && (
                  <li>
                    Import parcele fără geometrie —{" "}
                    <span className="font-medium text-amber-600 dark:text-amber-400">
                      {(() => {
                        const usefulNoGeom =
                          noGeomScan.qualityBreakdown.useful;
                        const newNoGeom = Math.max(
                          0,
                          usefulNoGeom - noGeomScan.localDbNoGeom,
                        );
                        const filtered = noGeomScan.qualityBreakdown.empty;
                        return newNoGeom > 0
                          ? `~${newNoGeom.toLocaleString("ro-RO")} noi de importat` +
                              (filtered > 0
                                ? ` (${filtered.toLocaleString("ro-RO")} filtrate)`
                                : "")
                          : "deja importate";
                      })()}
                    </span>
                  </li>
                )}
                <li>
                  \u00cembogățire CF, proprietari, adrese —{" "}
                  <span className="font-medium text-teal-600 dark:text-teal-400">
                    {(() => {
                      // What will be in DB after sync + optional no-geom import:
                      // If DB is empty: sync will add remoteGisCount geo features
                      // If DB is fresh: keep localDbTotal
                      const geoAfterSync =
                        noGeomScan.localSyncFresh &&
                        noGeomScan.localDbWithGeom > 0
                          ? noGeomScan.localDbWithGeom
                          : noGeomScan.remoteGisCount;
                      const noGeomAfterImport = includeNoGeom
                        ? Math.max(
                            noGeomScan.localDbNoGeom,
                            noGeomScan.qualityBreakdown.useful,
                          )
                        : noGeomScan.localDbNoGeom;
                      const totalAfter = geoAfterSync + noGeomAfterImport;
                      const remaining =
                        totalAfter - noGeomScan.localDbEnrichedComplete;
                      return remaining > 0
                        ? `~${remaining.toLocaleString("ro-RO")} de procesat (~${Math.ceil((remaining * 0.25) / 60)} min)`
                        : "deja îmbogățite";
                    })()}
                  </span>
                </li>
                <li>Generare GPKG + CSV</li>
                <li>Comprimare ZIP + descărcare</li>
              </ol>
            </div>
          );

          // No-geometry parcels found
          if (hasNoGeomParcels)
            return (
              <Card
                className={cn(
                  "transition-colors",
                  includeNoGeom
                    ? "border-amber-400 bg-amber-50/50 dark:border-amber-700 dark:bg-amber-950/20"
                    : "border-amber-200 dark:border-amber-800/50",
                )}
              >
                <CardContent className="py-3 px-4 space-y-2">
                  <div className="flex items-center gap-3">
                    <AlertTriangle className="h-4 w-4 text-amber-500 shrink-0" />
                    <div className="flex-1 min-w-0">
                      <p className="text-sm">
                        Layer GIS:{" "}
                        <span className="font-semibold">
                          {noGeomScan.remoteGisCount.toLocaleString("ro-RO")}
                        </span>{" "}
                        terenuri
                        {noGeomScan.remoteCladiriCount > 0 && (
                          <>
                            {" + "}
                            <span className="font-semibold">
                              {noGeomScan.remoteCladiriCount.toLocaleString(
                                "ro-RO",
                              )}
                            </span>{" "}
                            clădiri
                          </>
                        )}
                        {" · "}
                        Lista imobile:{" "}
                        <span className="font-semibold">
                          {noGeomScan.totalImmovables.toLocaleString("ro-RO")}
                        </span>
                        {" (estimat "}
                        <span className="font-semibold text-amber-600 dark:text-amber-400">
                          ~
                          {Math.max(
                            0,
                            noGeomScan.totalImmovables -
                              noGeomScan.remoteGisCount,
                          ).toLocaleString("ro-RO")}
                        </span>
                        {" fără geometrie)"}
                      </p>
                      <p className="text-[11px] text-muted-foreground mt-0.5">
                        Cele fără geometrie există în baza de date eTerra dar
                        nu au contur desenat în layerul GIS.
                      </p>
                      {localDbLine}
                    </div>
                    <Button
                      variant="ghost"
                      size="sm"
                      className="h-7 text-xs shrink-0"
                      disabled={noGeomScanning || exporting}
                      onClick={() => void handleNoGeomScan()}
                      title="Re-scanare"
                    >
                      <RefreshCw className="h-3 w-3" />
                    </Button>
                  </div>
                  <label className="flex items-center gap-2 cursor-pointer select-none ml-7">
                    <input
                      type="checkbox"
                      checked={includeNoGeom}
                      onChange={(e) => setIncludeNoGeom(e.target.checked)}
                      disabled={exporting}
                      className="h-4 w-4 rounded border-muted-foreground/30 accent-amber-600"
                    />
                    <span className="text-sm font-medium">
                      Include și parcelele fără geometrie la export
                    </span>
                  </label>
                  {/* Quality breakdown of no-geom items */}
                  {scanDone && noGeomScan.noGeomCount > 0 && (
                    <div className="ml-7 p-2 rounded-md bg-muted/40 space-y-1">
                      <p className="text-[11px] font-medium text-muted-foreground">
                        Calitate date (din{" "}
                        {noGeomScan.noGeomCount.toLocaleString("ro-RO")} fără
                        geometrie):
                      </p>
                      <div className="grid grid-cols-2 gap-x-4 gap-y-0.5 text-[11px] text-muted-foreground">
                        <span>
                          Cu nr. cadastral eTerra:{" "}
                          <span className="font-medium text-foreground">
                            {noGeomScan.qualityBreakdown.withCadRef.toLocaleString(
                              "ro-RO",
                            )}
                          </span>
                        </span>
                        <span>
                          Cu nr. CF/LB:{" "}
                          <span className="font-medium text-foreground">
                            {noGeomScan.qualityBreakdown.withPaperLb.toLocaleString(
                              "ro-RO",
                            )}
                          </span>
                        </span>
                        <span>
                          Cu nr. cad. pe hârtie:{" "}
                          <span className="font-medium text-foreground">
                            {noGeomScan.qualityBreakdown.withPaperCad.toLocaleString(
                              "ro-RO",
                            )}
                          </span>
                        </span>
                        <span>
                          Cu suprafață:{" "}
                          <span className="font-medium text-foreground">
                            {noGeomScan.qualityBreakdown.withArea.toLocaleString(
                              "ro-RO",
                            )}
                          </span>
                        </span>
                        <span>
                          Active (status=1):{" "}
                          <span className="font-medium text-foreground">
                            {noGeomScan.qualityBreakdown.withActiveStatus.toLocaleString(
                              "ro-RO",
                            )}
                          </span>
                        </span>
                        <span>
                          Cu carte funciară:{" "}
                          <span className="font-medium text-foreground">
                            {noGeomScan.qualityBreakdown.withLandbook.toLocaleString(
                              "ro-RO",
                            )}
                          </span>
                        </span>
                      </div>
                      <div className="flex items-center gap-3 text-[11px] pt-0.5 border-t border-muted-foreground/10">
                        <span>
                          Utilizabile:{" "}
                          <span className="font-semibold text-emerald-600 dark:text-emerald-400">
                            {noGeomScan.qualityBreakdown.useful.toLocaleString(
                              "ro-RO",
                            )}
                          </span>
                        </span>
                        {noGeomScan.qualityBreakdown.empty > 0 && (
                          <span>
                            Filtrate (fără CF/inactive/fără date):{" "}
                            <span className="font-semibold text-rose-600 dark:text-rose-400">
                              {noGeomScan.qualityBreakdown.empty.toLocaleString(
                                "ro-RO",
                              )}
                            </span>
                          </span>
                        )}
                      </div>
                    </div>
                  )}
                  {includeNoGeom && (
                    <p className="text-[11px] text-muted-foreground ml-7">
                      {noGeomScan.qualityBreakdown.empty > 0
                        ? `Din ${noGeomScan.noGeomCount.toLocaleString("ro-RO")} fără geometrie, ~${noGeomScan.qualityBreakdown.useful.toLocaleString("ro-RO")} vor fi importate (imobile electronice cu CF). ${noGeomScan.qualityBreakdown.empty.toLocaleString("ro-RO")} vor fi filtrate (fără carte funciară, inactive sau fără date).`
                        : "Vor fi importate în DB și incluse în CSV + Magic GPKG (coloana HAS_GEOMETRY=0/1)."}{" "}
                      \u00cen GPKG de bază apar doar cele cu geometrie.
                    </p>
                  )}
                  {workflowPreview}
                </CardContent>
              </Card>
            );

          // Scan done, all parcels have geometry (or totalImmovables=0 => workspace issue)
          if (scanDone && !hasNoGeomParcels)
            return (
              <Card className="border-dashed">
                <CardContent className="py-2.5 px-4">
                  <div className="flex items-center gap-2 text-xs text-muted-foreground">
                    {noGeomScan.totalImmovables > 0 ? (
                      <>
                        <CheckCircle2 className="h-3.5 w-3.5 text-emerald-500" />
                        Toate cele{" "}
                        {noGeomScan.totalImmovables.toLocaleString("ro-RO")}{" "}
                        imobile din eTerra au geometrie — nimic de importat
                        suplimentar.
                        {noGeomScan.localDbTotal > 0 && (
                          <span className="ml-1">
                            ({noGeomScan.localDbTotal.toLocaleString("ro-RO")}{" "}
                            în DB local
                            {noGeomScan.localDbEnriched > 0 &&
                              `, ${noGeomScan.localDbEnriched.toLocaleString("ro-RO")} îmbogățite`}
                            {noGeomScan.localDbEnriched > 0 &&
                              noGeomScan.localDbEnrichedComplete <
                                noGeomScan.localDbEnriched && (
                                <span className="text-orange-600 dark:text-orange-400">
                                  {` (${(noGeomScan.localDbEnriched - noGeomScan.localDbEnrichedComplete).toLocaleString("ro-RO")} incomplete)`}
                                </span>
                              )}
                            {noGeomScan.localSyncFresh && ", proaspăt"})
                          </span>
                        )}
                      </>
                    ) : (
                      <>
                        <AlertTriangle className="h-3.5 w-3.5 text-muted-foreground" />
                        Nu s-au găsit imobile în lista eTerra pentru acest
                        UAT. Verifică sesiunea eTerra.
                      </>
                    )}
                  </div>
                </CardContent>
              </Card>
            );

          return null;
        })()}

      {/* ── Background sync + Download from DB ──────────────── */}
      {sirutaValid && (
        <Card className="border-dashed">
          <CardContent className="py-3 px-4 space-y-3">
            {/* Row 1: Section label */}
            <div className="flex items-center gap-2">
              <HardDrive className="h-4 w-4 text-muted-foreground" />
              <span className="text-sm font-medium">
                Procesare fundal &amp; descărcare din DB
              </span>
              <span className="text-[10px] text-muted-foreground">
                — pornește sincronizarea, închide pagina, descarcă mai târziu
              </span>
            </div>

            {/* Include no-geom toggle (works independently of scan) */}
            {session.connected && (
              <label className="flex items-center gap-2 cursor-pointer select-none ml-6">
                <input
                  type="checkbox"
                  checked={includeNoGeom}
                  onChange={(e) => setIncludeNoGeom(e.target.checked)}
                  disabled={
                    exporting ||
                    (!!bgJobId && bgProgress?.status === "running")
                  }
                  className="h-4 w-4 rounded border-muted-foreground/30 accent-amber-600"
                />
                <span className="text-xs">
                  Include și parcelele fără geometrie
                </span>
                {noGeomScanning && (
                  <span className="text-[10px] text-muted-foreground">
                    (scanare în curs…)
                  </span>
                )}
              </label>
            )}

            {/* Row 2: Background sync buttons */}
            {session.connected && (
              <div className="grid gap-2 sm:grid-cols-2">
                <Button
                  variant="outline"
                  size="sm"
                  className="h-auto py-2.5 justify-start"
                  disabled={
                    exporting ||
                    (!!bgJobId && bgProgress?.status === "running")
                  }
                  onClick={() => void handleSyncBackground("base")}
                >
                  {bgJobId &&
                  bgProgress?.status === "running" &&
                  !bgPhaseTrail.some((p) => p.includes("\u00cembogățire")) ? (
                    <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                  ) : (
                    <ArrowDownToLine className="mr-2 h-4 w-4" />
                  )}
                  <div className="text-left">
                    <div className="text-xs font-semibold">
                      Sync fundal — Bază
                    </div>
                    <div className="text-[10px] opacity-60 font-normal">
                      Terenuri + clădiri → salvează în DB
                    </div>
                  </div>
                </Button>
                <Button
                  variant="outline"
                  size="sm"
                  className="h-auto py-2.5 justify-start border-teal-200 dark:border-teal-800 hover:bg-teal-50 dark:hover:bg-teal-950/30"
                  disabled={
                    exporting ||
                    (!!bgJobId && bgProgress?.status === "running")
                  }
                  onClick={() => void handleSyncBackground("magic")}
                >
                  {bgJobId &&
                  bgProgress?.status === "running" &&
                  bgPhaseTrail.some((p) => p.includes("\u00cembogățire")) ? (
                    <Loader2 className="mr-2 h-4 w-4 animate-spin text-teal-600" />
                  ) : (
                    <Sparkles className="mr-2 h-4 w-4 text-teal-600" />
                  )}
                  <div className="text-left">
                    <div className="text-xs font-semibold">
                      Sync fundal — Magic
                    </div>
                    <div className="text-[10px] opacity-60 font-normal">
                      Sync + îmbogățire → salvează în DB
                    </div>
                  </div>
                </Button>
              </div>
            )}

            {/* Row 3: Download from DB buttons */}
            {dbTotalFeatures > 0 && (
              <div className="grid gap-2 sm:grid-cols-2">
                <Button
                  variant="outline"
                  size="sm"
                  className="h-auto py-2.5 justify-start"
                  disabled={downloadingFromDb}
                  onClick={() => void handleDownloadFromDb("base")}
                >
                  {downloadingFromDb ? (
                    <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                  ) : (
                    <Database className="mr-2 h-4 w-4" />
                  )}
                  <div className="text-left">
                    <div className="text-xs font-semibold">
                      Descarcă din DB — Bază
                    </div>
                    <div className="text-[10px] opacity-60 font-normal">
                      GPKG terenuri + clădiri (instant, fără eTerra)
                    </div>
                  </div>
                </Button>
                <Button
                  variant="outline"
                  size="sm"
                  className="h-auto py-2.5 justify-start border-teal-200 dark:border-teal-800 hover:bg-teal-50 dark:hover:bg-teal-950/30"
                  disabled={downloadingFromDb}
                  onClick={() => void handleDownloadFromDb("magic")}
                >
                  {downloadingFromDb ? (
                    <Loader2 className="mr-2 h-4 w-4 animate-spin text-teal-600" />
                  ) : (
                    <Sparkles className="mr-2 h-4 w-4 text-teal-600" />
                  )}
                  <div className="text-left">
                    <div className="text-xs font-semibold">
                      Descarcă din DB — Magic
                    </div>
                    <div className="text-[10px] opacity-60 font-normal">
                      GPKG + CSV + raport calitate (instant)
                    </div>
                  </div>
                </Button>
              </div>
            )}

            {!session.connected && dbTotalFeatures === 0 && (
              <p className="text-xs text-muted-foreground ml-6">
                Conectează-te la eTerra pentru a porni sincronizarea fundal,
                sau sincronizează mai întâi date în baza locală.
              </p>
            )}
          </CardContent>
        </Card>
      )}

      {/* Background sync progress */}
      {bgJobId && bgProgress && bgProgress.status !== "unknown" && (
        <Card
          className={cn(
            "border-2 transition-colors",
            bgProgress.status === "running" &&
              "border-indigo-300 dark:border-indigo-700",
            bgProgress.status === "error" &&
              "border-rose-300 dark:border-rose-700",
            bgProgress.status === "done" &&
              "border-emerald-400 dark:border-emerald-600",
          )}
        >
          <CardContent className="pt-4 space-y-3">
            {/* Label */}
            <div className="flex items-center gap-2 text-xs">
              <HardDrive className="h-3.5 w-3.5 text-indigo-500" />
              <span className="font-semibold text-indigo-700 dark:text-indigo-400">
                Sincronizare fundal
              </span>
              {bgProgress.status === "running" && (
                <span className="text-muted-foreground">
                  (poți închide pagina)
                </span>
              )}
            </div>

            {/* Phase trail */}
            <div className="flex items-center gap-2 flex-wrap text-xs text-muted-foreground">
              {bgPhaseTrail.map((p, i) => (
                <span key={i} className="flex items-center gap-1">
                  {i > 0 && <span className="opacity-40">→</span>}
                  <span
                    className={cn(
                      i === bgPhaseTrail.length - 1
                        ? "font-semibold text-foreground"
                        : "opacity-60",
                    )}
                  >
                    {p}
                  </span>
                </span>
              ))}
            </div>

            {/* Progress info */}
            <div className="flex items-center gap-3">
              {bgProgress.status === "running" && (
                <Loader2 className="h-5 w-5 text-indigo-600 animate-spin shrink-0" />
              )}
              {bgProgress.status === "done" && (
                <CheckCircle2 className="h-5 w-5 text-emerald-600 shrink-0" />
              )}
              {bgProgress.status === "error" && (
                <XCircle className="h-5 w-5 text-rose-500 shrink-0" />
              )}
              <div className="min-w-0 flex-1">
                <p className="text-sm font-medium">{bgProgress.phase}</p>
                {bgProgress.note && (
                  <p className="text-xs text-muted-foreground">
                    {bgProgress.note}
                  </p>
                )}
                {bgProgress.message && (
                  <p
                    className={cn(
                      "text-xs mt-0.5",
                      bgProgress.status === "error"
                        ? "text-rose-500"
                        : "text-muted-foreground",
                    )}
                  >
                    {bgProgress.message}
                  </p>
                )}
              </div>
              <span className="text-sm font-mono font-semibold tabular-nums shrink-0">
                {bgProgress.total && bgProgress.total > 0
                  ? Math.round(
                      (bgProgress.downloaded / bgProgress.total) * 100,
                    )
                  : 0}
                %
              </span>
            </div>

            {/* Bar */}
            <div className="h-2.5 w-full rounded-full bg-muted">
              <div
                className={cn(
                  "h-2.5 rounded-full transition-all duration-300",
                  bgProgress.status === "running" && "bg-indigo-500",
                  bgProgress.status === "done" && "bg-emerald-500",
                  bgProgress.status === "error" && "bg-rose-500",
                )}
                style={{
                  width: `${Math.max(2, bgProgress.total && bgProgress.total > 0 ? Math.round((bgProgress.downloaded / bgProgress.total) * 100) : 0)}%`,
                }}
              />
            </div>

            {/* Done — show download from DB button */}
            {bgProgress.status === "done" && (
              <div className="flex gap-2 pt-1">
                <Button
                  variant="outline"
                  size="sm"
                  className="text-xs border-teal-200 dark:border-teal-800"
                  disabled={downloadingFromDb}
                  onClick={() => void handleDownloadFromDb("magic")}
                >
                  {downloadingFromDb ? (
                    <Loader2 className="mr-1.5 h-3 w-3 animate-spin" />
                  ) : (
                    <Database className="mr-1.5 h-3 w-3" />
                  )}
                  Descarcă din DB (Magic)
                </Button>
                <Button
                  variant="ghost"
                  size="sm"
                  className="text-xs"
                  onClick={() => {
                    setBgJobId(null);
                    setBgProgress(null);
                    setBgPhaseTrail([]);
                  }}
                >
                  \u00cenchide
                </Button>
              </div>
            )}
          </CardContent>
        </Card>
      )}

      {/* Progress bar for bundle export */}
      {exportProgress &&
        exportProgress.status !== "unknown" &&
        exportJobId && (
          <Card
            className={cn(
              "border-2 transition-colors",
              exportProgress.status === "running" &&
                "border-emerald-300 dark:border-emerald-700",
              exportProgress.status === "error" &&
                "border-rose-300 dark:border-rose-700",
              exportProgress.status === "done" &&
                "border-emerald-400 dark:border-emerald-600",
            )}
          >
            <CardContent className="pt-4 space-y-3">
              {/* Phase trail */}
              <div className="flex items-center gap-2 flex-wrap text-xs text-muted-foreground">
                {phaseTrail.map((p, i) => (
                  <span key={i} className="flex items-center gap-1">
                    {i > 0 && <span className="opacity-40">→</span>}
                    <span
                      className={cn(
                        i === phaseTrail.length - 1
                          ? "font-semibold text-foreground"
                          : "opacity-60",
                      )}
                    >
                      {p}
                    </span>
                  </span>
                ))}
              </div>

              {/* Progress info */}
              <div className="flex items-center gap-3">
                {exportProgress.status === "running" && (
                  <Loader2 className="h-5 w-5 text-emerald-600 animate-spin shrink-0" />
                )}
                {exportProgress.status === "done" && (
                  <CheckCircle2 className="h-5 w-5 text-emerald-600 shrink-0" />
                )}
                {exportProgress.status === "error" && (
                  <XCircle className="h-5 w-5 text-rose-500 shrink-0" />
                )}
                <div className="min-w-0 flex-1">
                  <p className="text-sm font-medium">
                    {exportProgress.phase}
                    {exportProgress.phaseCurrent != null &&
                    exportProgress.phaseTotal
                      ? ` — ${exportProgress.phaseCurrent} / ${exportProgress.phaseTotal}`
                      : ""}
                  </p>
                  {exportProgress.note && (
                    <p className="text-xs text-muted-foreground">
                      {exportProgress.note}
                    </p>
                  )}
                  {exportProgress.message && (
                    <p
                      className={cn(
                        "text-xs mt-0.5",
                        exportProgress.status === "error"
                          ? "text-rose-500"
                          : "text-muted-foreground",
                      )}
                    >
                      {exportProgress.message}
                    </p>
                  )}
                </div>
                <span className="text-sm font-mono font-semibold tabular-nums shrink-0">
                  {progressPct}%
                </span>
              </div>

              {/* Bar */}
              <div className="h-2.5 w-full rounded-full bg-muted">
                <div
                  className={cn(
                    "h-2.5 rounded-full transition-all duration-300",
                    exportProgress.status === "running" && "bg-emerald-500",
                    exportProgress.status === "done" && "bg-emerald-500",
                    exportProgress.status === "error" && "bg-rose-500",
                  )}
                  style={{ width: `${Math.max(2, progressPct)}%` }}
                />
              </div>
            </CardContent>
          </Card>
        )}
    </div>
  );
}
