"use client";

import { useState, useCallback, useEffect, useMemo, useRef } from "react";
import {
  Search,
  Layers,
  Loader2,
  ChevronDown,
  ChevronUp,
  Download,
  CheckCircle2,
  XCircle,
  RefreshCw,
  Database,
  HardDrive,
  Sparkles,
} 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 {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from "@/shared/components/ui/tooltip";
import { cn } from "@/shared/lib/utils";
import {
  LAYER_CATALOG,
  LAYER_CATEGORY_LABELS,
  type LayerCategory,
  type LayerCatalogItem,
} from "../../services/eterra-layers";
import type {
  SessionStatus,
  SyncRunInfo,
  ExportProgress,
} from "../parcel-sync-types";

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

type LayersTabProps = {
  siruta: string;
  sirutaValid: boolean;
  session: SessionStatus;
  syncLocalCounts: Record<string, number>;
  syncRuns: SyncRunInfo[];
  syncingSiruta: string;
  onSyncRefresh: () => void;
  exporting: boolean;
};

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

export function LayersTab({
  siruta,
  sirutaValid,
  session,
  syncLocalCounts,
  syncRuns,
  syncingSiruta,
  onSyncRefresh,
  exporting,
}: LayersTabProps) {
  /* ── Local state ──────────────────────────────────────────────── */
  const [expandedCategories, setExpandedCategories] = useState<
    Record<string, boolean>
  >({});
  const [downloadingLayer, setDownloadingLayer] = useState<string | null>(null);
  const [layerCounts, setLayerCounts] = useState<
    Record<string, { count: number; error?: string }>
  >({});
  const [countingLayers, setCountingLayers] = useState(false);
  const [layerCountSiruta, setLayerCountSiruta] = useState("");
  const [layerHistory, setLayerHistory] = useState<
    {
      layerId: string;
      label: string;
      count: number;
      time: string;
      siruta: string;
    }[]
  >([]);
  const [syncingLayer, setSyncingLayer] = useState<string | null>(null);
  const [syncProgress, setSyncProgress] = useState("");
  const [syncQueue, setSyncQueue] = useState<string[]>([]);
  const syncQueueRef = useRef<string[]>([]);
  const [exportingLocal, setExportingLocal] = useState(false);
  const [postgisRunning, setPostgisRunning] = useState(false);
  const [postgisResult, setPostgisResult] = useState<{
    success: boolean;
    message?: string;
    details?: Record<string, unknown>;
    error?: string;
  } | null>(null);
  const [exportProgress, setExportProgress] = useState<ExportProgress | null>(
    null,
  );
  const [phaseTrail, setPhaseTrail] = useState<string[]>([]);

  const pollingRef = useRef<ReturnType<typeof setInterval> | null>(null);

  /* ── Derived ──────────────────────────────────────────────────── */

  const layersByCategory = useMemo(() => {
    const grouped: Record<string, LayerCatalogItem[]> = {};
    for (const layer of LAYER_CATALOG) {
      if (!grouped[layer.category]) grouped[layer.category] = [];
      grouped[layer.category]!.push(layer);
    }
    return grouped;
  }, []);

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

  /* ── Layer history: load from localStorage on mount ───────────── */

  useEffect(() => {
    try {
      const raw = localStorage.getItem("parcel-sync:layer-history");
      if (raw) {
        const parsed = JSON.parse(raw) as typeof layerHistory;
        const today = new Date().toISOString().slice(0, 10);
        const todayEntries = parsed.filter(
          (e) => e.time.slice(0, 10) === today,
        );
        setLayerHistory(todayEntries);
      }
    } catch {
      // ignore
    }
  }, []);

  /* ── Cleanup polling on unmount ───────────────────────────────── */

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

  /* ── startPolling ─────────────────────────────────────────────── */

  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);
  }, []);

  /* ── fetchLayerCounts ─────────────────────────────────────────── */

  const fetchLayerCounts = useCallback(async () => {
    if (!siruta || countingLayers) return;
    setCountingLayers(true);
    try {
      const res = await fetch("/api/eterra/layers/summary", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ siruta }),
      });
      const data = (await res.json()) as {
        counts?: Record<string, { count: number; error?: string }>;
        error?: string;
      };
      if (data.counts) {
        setLayerCounts(data.counts);
        setLayerCountSiruta(siruta);

        // Save non-zero counts to history
        const now = new Date().toISOString();
        const today = now.slice(0, 10);
        const newEntries: typeof layerHistory = [];
        for (const [layerId, info] of Object.entries(data.counts)) {
          if (info.count > 0) {
            const layer = LAYER_CATALOG.find((l) => l.id === layerId);
            newEntries.push({
              layerId,
              label: layer?.label ?? layerId,
              count: info.count,
              time: now,
              siruta,
            });
          }
        }
        setLayerHistory((prev) => {
          // Keep today's entries only, add new batch
          const kept = prev.filter(
            (e) => e.time.slice(0, 10) === today && e.siruta !== siruta,
          );
          const merged = [...kept, ...newEntries];
          try {
            localStorage.setItem(
              "parcel-sync:layer-history",
              JSON.stringify(merged),
            );
          } catch {
            // quota
          }
          return merged;
        });
      }
    } catch {
      // silent
    }
    setCountingLayers(false);
  }, [siruta, countingLayers]);

  /* ── handleSyncLayer ──────────────────────────────────────────── */

  const handleSyncLayer = useCallback(
    async (layerId: string) => {
      if (!siruta || syncingLayer) return;
      setSyncingLayer(layerId);
      setSyncProgress("Sincronizare pornită…");
      try {
        const res = await fetch("/api/eterra/sync", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            siruta,
            layerId,
            jobId: crypto.randomUUID(),
          }),
        });
        const data = (await res.json()) as {
          status?: string;
          newFeatures?: number;
          removedFeatures?: number;
          totalLocal?: number;
          error?: string;
        };
        if (data.error) {
          setSyncProgress(`Eroare: ${data.error}`);
        } else {
          setSyncProgress(
            `Finalizat — ${data.newFeatures ?? 0} noi, ${data.removedFeatures ?? 0} șterse, ${data.totalLocal ?? 0} total local`,
          );
          // Refresh sync status
          onSyncRefresh();
        }
      } catch {
        setSyncProgress("Eroare rețea");
      }
      // Clear progress after 8s
      setTimeout(() => {
        setSyncingLayer(null);
        setSyncProgress("");
      }, 8_000);
    },
    [siruta, syncingLayer, onSyncRefresh],
  );

  /* ── handleExportLocal ────────────────────────────────────────── */

  const handleExportLocal = useCallback(
    async (layerIds?: string[]) => {
      if (!siruta || exportingLocal) return;
      setExportingLocal(true);
      try {
        const res = await fetch("/api/eterra/export-local", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            siruta,
            ...(layerIds ? { layerIds } : { allLayers: true }),
          }),
        });
        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_local_${siruta}.${layerIds?.length === 1 ? "gpkg" : "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 export";
        setSyncProgress(msg);
        setTimeout(() => setSyncProgress(""), 5_000);
      }
      setExportingLocal(false);
    },
    [siruta, exportingLocal],
  );

  /* ── handleSyncMultiple ───────────────────────────────────────── */

  const handleSyncMultiple = useCallback(
    async (layerIds: string[]) => {
      if (!siruta || syncingLayer || syncQueue.length > 0) return;
      syncQueueRef.current = [...layerIds];
      setSyncQueue([...layerIds]);

      for (const layerId of layerIds) {
        setSyncingLayer(layerId);
        setSyncProgress(
          `Sincronizare ${LAYER_CATALOG.find((l) => l.id === layerId)?.label ?? layerId}…`,
        );
        try {
          const res = await fetch("/api/eterra/sync", {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({
              siruta,
              layerId,
              jobId: crypto.randomUUID(),
            }),
          });
          const data = (await res.json()) as {
            error?: string;
            newFeatures?: number;
            removedFeatures?: number;
            totalLocal?: number;
          };
          if (data.error) {
            setSyncProgress(`Eroare: ${data.error}`);
          }
        } catch {
          setSyncProgress("Eroare rețea");
        }
        // Remove from queue
        syncQueueRef.current = syncQueueRef.current.filter(
          (id) => id !== layerId,
        );
        setSyncQueue([...syncQueueRef.current]);
      }
      // Done — refresh status
      onSyncRefresh();
      setSyncingLayer(null);
      setSyncProgress("");
      setSyncQueue([]);
      syncQueueRef.current = [];
    },
    [siruta, syncingLayer, syncQueue.length, onSyncRefresh],
  );

  /* ── handleSetupPostgis ───────────────────────────────────────── */

  const handleSetupPostgis = useCallback(async () => {
    if (postgisRunning) return;
    setPostgisRunning(true);
    setPostgisResult(null);
    try {
      const res = await fetch("/api/eterra/setup-postgis", { method: "POST" });
      const json = await res.json();
      setPostgisResult(json as typeof postgisResult);
    } catch (error) {
      const msg = error instanceof Error ? error.message : "Eroare setup";
      setPostgisResult({ success: false, error: msg });
    }
    setPostgisRunning(false);
  }, [postgisRunning, postgisResult]);

  /* ── handleExportLayer ────────────────────────────────────────── */

  const handleExportLayer = useCallback(
    async (layerId: string) => {
      if (!siruta || downloadingLayer) return;
      setDownloadingLayer(layerId);
      const jobId = crypto.randomUUID();
      setExportProgress(null);
      setPhaseTrail([]);

      startPolling(jobId);

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

        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}_${layerId}.gpkg`;

        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;
      }
      setDownloadingLayer(null);
      // Refresh sync status — layer was synced to DB
      onSyncRefresh();
    },
    [siruta, downloadingLayer, startPolling, onSyncRefresh],
  );

  /* ── Suppress unused warnings for sync multiple (used externally) */
  void handleSyncMultiple;
  void phaseTrail;
  void syncQueue;

  /* ── JSX ──────────────────────────────────────────────────────── */

  if (!sirutaValid || !session.connected) {
    return (
      <Card>
        <CardContent className="py-12 text-center text-muted-foreground">
          <Layers className="h-10 w-10 mx-auto mb-3 opacity-30" />
          <p>
            {!session.connected
              ? "Conectează-te la eTerra și selectează un UAT."
              : "Selectează un UAT pentru a vedea catalogul de layere."}
          </p>
        </CardContent>
      </Card>
    );
  }

  return (
    <div className="space-y-3">
      {/* Action bar */}
      <div className="flex items-center justify-between gap-2 flex-wrap">
        <p className="text-xs text-muted-foreground">
          {layerCountSiruta === siruta &&
          Object.keys(layerCounts).length > 0
            ? `Număr features pentru SIRUTA ${siruta}`
            : "Apasă pentru a număra features-urile din fiecare layer."}
        </p>
        <div className="flex items-center gap-2">
          {/* Export from local DB */}
          {syncingSiruta === siruta &&
            Object.values(syncLocalCounts).some((c) => c > 0) && (
              <Button
                size="sm"
                variant="outline"
                disabled={exportingLocal}
                onClick={() => void handleExportLocal()}
                className="border-violet-300 text-violet-700 dark:border-violet-700 dark:text-violet-300"
              >
                {exportingLocal ? (
                  <Loader2 className="h-3.5 w-3.5 animate-spin mr-1.5" />
                ) : (
                  <HardDrive className="h-3.5 w-3.5 mr-1.5" />
                )}
                Export local
              </Button>
            )}
          <Button
            size="sm"
            variant="outline"
            disabled={countingLayers}
            onClick={() => void fetchLayerCounts()}
          >
            {countingLayers ? (
              <Loader2 className="h-3.5 w-3.5 animate-spin mr-1.5" />
            ) : (
              <Search className="h-3.5 w-3.5 mr-1.5" />
            )}
            {countingLayers ? "Se numără…" : "Numără"}
          </Button>
        </div>
      </div>

      {/* Sync progress message */}
      {syncProgress && (
        <div className="flex items-center gap-2 rounded-lg border px-3 py-2 text-xs">
          {syncingLayer ? (
            <Loader2 className="h-3.5 w-3.5 animate-spin text-blue-500 shrink-0" />
          ) : (
            <CheckCircle2 className="h-3.5 w-3.5 text-emerald-500 shrink-0" />
          )}
          <span>{syncProgress}</span>
        </div>
      )}

      {(Object.keys(LAYER_CATEGORY_LABELS) as LayerCategory[]).map((cat) => {
        const layers = layersByCategory[cat];
        if (!layers?.length) return null;
        const isExpanded = expandedCategories[cat] ?? false;

        // Sum counts for category badge
        const catTotal =
          layerCountSiruta === siruta
            ? layers.reduce(
                (sum, l) => sum + (layerCounts[l.id]?.count ?? 0),
                0,
              )
            : null;

        // Sum local counts for category
        const catLocal =
          syncingSiruta === siruta
            ? layers.reduce(
                (sum, l) => sum + (syncLocalCounts[l.id] ?? 0),
                0,
              )
            : null;

        return (
          <Card key={cat}>
            <button
              type="button"
              className="w-full flex items-center justify-between px-4 py-3 text-left hover:bg-muted/50 transition-colors rounded-t-xl"
              onClick={() =>
                setExpandedCategories((prev) => ({
                  ...prev,
                  [cat]: !prev[cat],
                }))
              }
            >
              <div className="flex items-center gap-2 flex-wrap">
                <span className="text-sm font-semibold">
                  {LAYER_CATEGORY_LABELS[cat]}
                </span>
                <Badge
                  variant="outline"
                  className="font-normal text-[11px]"
                >
                  {layers.length}
                </Badge>
                {catTotal != null && catTotal > 0 && (
                  <Badge className="font-mono text-[10px] bg-blue-100 text-blue-700 dark:bg-blue-900/40 dark:text-blue-300 border-0">
                    {catTotal.toLocaleString("ro-RO")} remote
                  </Badge>
                )}
                {catLocal != null && catLocal > 0 && (
                  <Badge className="font-mono text-[10px] bg-violet-100 text-violet-700 dark:bg-violet-900/40 dark:text-violet-300 border-0">
                    {catLocal.toLocaleString("ro-RO")} local
                  </Badge>
                )}
              </div>
              {isExpanded ? (
                <ChevronUp className="h-4 w-4 text-muted-foreground" />
              ) : (
                <ChevronDown className="h-4 w-4 text-muted-foreground" />
              )}
            </button>

            {isExpanded && (
              <CardContent className="pt-0 pb-3 space-y-1.5">
                {layers.map((layer) => {
                  const isDownloading = downloadingLayer === layer.id;
                  const isSyncing = syncingLayer === layer.id;
                  const lc =
                    layerCountSiruta === siruta
                      ? layerCounts[layer.id]
                      : undefined;
                  const localCount =
                    syncingSiruta === siruta
                      ? (syncLocalCounts[layer.id] ?? 0)
                      : 0;

                  // Find last sync run for this layer
                  const lastRun = syncRuns.find(
                    (r) =>
                      r.layerId === layer.id && r.status === "done",
                  );

                  return (
                    <div
                      key={layer.id}
                      className={cn(
                        "rounded-lg border px-3 py-2.5 transition-colors",
                        isDownloading || isSyncing
                          ? "border-blue-300 bg-blue-50/50 dark:border-blue-700 dark:bg-blue-950/20"
                          : "hover:bg-muted/50",
                      )}
                    >
                      <div className="flex items-center justify-between gap-3">
                        <div className="min-w-0 flex-1">
                          <div className="flex items-center gap-2 flex-wrap">
                            <p className="text-sm font-medium truncate">
                              {layer.label}
                            </p>
                            {lc != null && !lc.error && (
                              <Badge
                                variant="secondary"
                                className={cn(
                                  "font-mono text-[10px] shrink-0",
                                  lc.count === 0
                                    ? "opacity-40"
                                    : "bg-emerald-100 text-emerald-700 dark:bg-emerald-900/40 dark:text-emerald-300",
                                )}
                              >
                                {lc.count.toLocaleString("ro-RO")}
                              </Badge>
                            )}
                            {lc?.error && (
                              <span className="text-[10px] text-rose-500">
                                eroare
                              </span>
                            )}
                            {localCount > 0 && (
                              <Badge className="font-mono text-[10px] bg-violet-100 text-violet-700 dark:bg-violet-900/40 dark:text-violet-300 border-0 shrink-0">
                                <Database className="h-2.5 w-2.5 mr-0.5" />
                                {localCount.toLocaleString("ro-RO")}
                              </Badge>
                            )}
                          </div>
                          <div className="flex items-center gap-2">
                            <p className="text-[11px] text-muted-foreground font-mono">
                              {layer.id}
                            </p>
                            {lastRun && (
                              <span className="text-[10px] text-muted-foreground/70">
                                sync{" "}
                                {new Date(
                                  lastRun.completedAt ??
                                    lastRun.startedAt,
                                ).toLocaleDateString("ro-RO", {
                                  day: "2-digit",
                                  month: "2-digit",
                                  hour: "2-digit",
                                  minute: "2-digit",
                                })}
                              </span>
                            )}
                          </div>
                        </div>
                        <div className="flex items-center gap-1.5 shrink-0">
                          {/* Sync to DB */}
                          <Button
                            size="sm"
                            variant="outline"
                            disabled={
                              !!syncingLayer ||
                              !!downloadingLayer ||
                              exporting
                            }
                            onClick={() =>
                              void handleSyncLayer(layer.id)
                            }
                            className="border-violet-200 dark:border-violet-800"
                            title="Sincronizează în baza de date"
                          >
                            {isSyncing ? (
                              <Loader2 className="h-3.5 w-3.5 animate-spin" />
                            ) : (
                              <RefreshCw className="h-3.5 w-3.5" />
                            )}
                            <span className="ml-1.5 hidden sm:inline">
                              Sync
                            </span>
                          </Button>
                          {/* GPKG (sync-first: syncs to DB if needed, then exports from DB) */}
                          <Button
                            size="sm"
                            variant="outline"
                            disabled={!!downloadingLayer || exporting}
                            onClick={() =>
                              void handleExportLayer(layer.id)
                            }
                            title={
                              localCount > 0
                                ? "Descarcă GPKG (din cache dacă e proaspăt)"
                                : "Sincronizează + descarcă GPKG"
                            }
                          >
                            {isDownloading ? (
                              <Loader2 className="h-3.5 w-3.5 animate-spin" />
                            ) : (
                              <Download className="h-3.5 w-3.5" />
                            )}
                            <span className="ml-1.5 hidden sm:inline">
                              GPKG
                            </span>
                          </Button>
                        </div>
                      </div>
                    </div>
                  );
                })}
              </CardContent>
            )}
          </Card>
        );
      })}

      {/* Drumul de azi — today's layer count history */}
      {layerHistory.length > 0 && (
        <Card>
          <div className="px-4 py-3 border-b">
            <div className="flex items-center gap-2">
              <Sparkles className="h-4 w-4 text-amber-500" />
              <span className="text-sm font-semibold">Drumul de azi</span>
              <Badge
                variant="outline"
                className="font-normal text-[11px]"
              >
                {layerHistory.length}
              </Badge>
            </div>
          </div>
          <CardContent className="pt-3 pb-3">
            <div className="space-y-2 max-h-64 overflow-y-auto">
              {/* Group by siruta */}
              {(() => {
                const grouped = new Map<string, typeof layerHistory>();
                for (const e of layerHistory) {
                  if (!grouped.has(e.siruta)) grouped.set(e.siruta, []);
                  grouped.get(e.siruta)!.push(e);
                }
                return Array.from(grouped.entries()).map(
                  ([sir, entries]) => (
                    <div key={sir} className="space-y-1">
                      <p className="text-[11px] font-semibold text-muted-foreground">
                        SIRUTA {sir}{" "}
                        <span className="font-normal opacity-70">
                          —{" "}
                          {new Date(entries[0]!.time).toLocaleTimeString(
                            "ro-RO",
                            { hour: "2-digit", minute: "2-digit" },
                          )}
                        </span>
                      </p>
                      <div className="grid grid-cols-2 sm:grid-cols-3 gap-1">
                        {entries
                          .sort((a, b) => b.count - a.count)
                          .map((e) => (
                            <div
                              key={e.layerId}
                              className="flex items-center justify-between gap-1 rounded border px-2 py-1 text-[11px]"
                            >
                              <span className="truncate">{e.label}</span>
                              <span className="font-mono font-semibold text-emerald-600 dark:text-emerald-400 shrink-0">
                                {e.count.toLocaleString("ro-RO")}
                              </span>
                            </div>
                          ))}
                      </div>
                    </div>
                  ),
                );
              })()}
            </div>
          </CardContent>
        </Card>
      )}

      {/* PostGIS / QGIS setup */}
      <Card>
        <div className="px-4 py-3 border-b">
          <div className="flex items-center justify-between">
            <div className="flex items-center gap-2">
              <Database className="h-4 w-4 text-violet-500" />
              <span className="text-sm font-semibold">
                Conectare QGIS
              </span>
            </div>
            {!postgisResult?.success && (
              <TooltipProvider>
                <Tooltip>
                  <TooltipTrigger asChild>
                    <Button
                      size="sm"
                      variant="outline"
                      disabled={postgisRunning}
                      onClick={() => void handleSetupPostgis()}
                      className="border-violet-300 text-violet-700 dark:border-violet-700 dark:text-violet-300"
                    >
                      {postgisRunning ? (
                        <Loader2 className="h-3.5 w-3.5 animate-spin mr-1.5" />
                      ) : (
                        <Database className="h-3.5 w-3.5 mr-1.5" />
                      )}
                      {postgisRunning
                        ? "Se activeaza…"
                        : "Activeaza compatibilitate QGIS"}
                    </Button>
                  </TooltipTrigger>
                  <TooltipContent className="max-w-xs">
                    <p className="font-medium">
                      Operatie sigura, reversibila
                    </p>
                    <p className="text-xs mt-1">
                      Creeaza coloane native PostGIS + view-uri read-only
                      pentru QGIS. Nu modifica datele existente. Ruleaza o
                      singura data (~30s).
                    </p>
                  </TooltipContent>
                </Tooltip>
              </TooltipProvider>
            )}
          </div>
        </div>
        <CardContent className="py-3 space-y-3">
          {postgisResult ? (
            postgisResult.success ? (
              <div className="space-y-3">
                <div className="flex items-center gap-2">
                  <CheckCircle2 className="h-4 w-4 text-emerald-500" />
                  <span className="text-sm font-medium text-emerald-700 dark:text-emerald-400">
                    QGIS compatibil — gata de conectare
                  </span>
                </div>
                <div className="rounded bg-muted/50 p-3 text-xs space-y-2">
                  <p className="font-medium text-sm">
                    Cum te conectezi din QGIS:
                  </p>
                  <ol className="list-decimal list-inside space-y-1 text-muted-foreground">
                    <li>
                      QGIS → Layer → Add Layer → Add PostGIS Layers
                    </li>
                    <li>New connection:</li>
                  </ol>
                  <div className="font-mono bg-background rounded px-2 py-1.5 space-y-0.5">
                    <p>
                      Host: <strong>10.10.10.166</strong>
                    </p>
                    <p>
                      Port: <strong>5432</strong>
                    </p>
                    <p>
                      Database: <strong>architools_db</strong>
                    </p>
                    <p>
                      Username: <strong>architools_user</strong>
                    </p>
                  </div>
                  <p className="text-muted-foreground">
                    View-uri disponibile (read-only):
                  </p>
                  <div className="font-mono text-muted-foreground">
                    gis_terenuri, gis_cladiri, gis_documentatii,
                    gis_administrativ
                  </div>
                  <p className="text-muted-foreground">
                    SRID: 3844 (Stereo70)
                  </p>
                  {postgisResult.details && (
                    <p className="text-muted-foreground">
                      {String(
                        (
                          postgisResult.details as {
                            totalFeaturesWithGeom?: number;
                          }
                        ).totalFeaturesWithGeom ?? 0,
                      )}{" "}
                      features cu geometrie nativa
                    </p>
                  )}
                </div>
              </div>
            ) : (
              <div className="flex items-start gap-2">
                <XCircle className="h-4 w-4 text-red-500 shrink-0 mt-0.5" />
                <div className="text-sm">
                  <p className="font-medium text-red-700 dark:text-red-400">
                    PostGIS nu este instalat pe server
                  </p>
                  <p className="text-xs text-muted-foreground mt-1">
                    Contacteaza administratorul pentru instalare:
                  </p>
                  <code className="text-xs block mt-1 bg-muted rounded px-2 py-1">
                    apt install postgresql-16-postgis-3
                  </code>
                </div>
              </div>
            )
          ) : (
            <div className="text-xs text-muted-foreground space-y-2">
              <p>
                Permite conectarea din QGIS direct la baza de date pentru
                vizualizare si analiza spatiala a parcelelor, cladirilor
                si limitelor UAT.
              </p>
              <p>
                Apasa butonul pentru a activa — creeaza view-uri read-only
                (nu modifica datele, nu afecteaza performanta aplicatiei).
              </p>
            </div>
          )}
        </CardContent>
      </Card>

      {/* Progress bar for layer download */}
      {downloadingLayer && exportProgress && (
        <Card className="border-blue-200 dark:border-blue-800">
          <CardContent className="pt-4 space-y-2">
            <div className="flex items-center gap-3">
              <Loader2 className="h-5 w-5 text-blue-600 animate-spin 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>
              </div>
              <span className="text-sm font-mono font-semibold tabular-nums">
                {progressPct}%
              </span>
            </div>
            <div className="h-2 w-full rounded-full bg-blue-200/50 dark:bg-blue-800/30">
              <div
                className="h-2 rounded-full bg-blue-600 transition-all duration-300"
                style={{ width: `${Math.max(2, progressPct)}%` }}
              />
            </div>
          </CardContent>
        </Card>
      )}
    </div>
  );
}
