"use client";

import { useState, useEffect, useCallback, useRef } from "react";

type MonitorData = {
  timestamp: string;
  nginx?: { activeConnections?: number; requests?: number; reading?: number; writing?: number; waiting?: number; error?: string };
  martin?: { status?: string; sources?: string[]; sourceCount?: number; error?: string };
  pmtiles?: { url?: string; status?: string; size?: string; lastModified?: string; error?: string };
  cacheTests?: { tile: string; status: string; cache: string }[];
  config?: { martinUrl?: string; pmtilesUrl?: string; n8nWebhook?: string };
};

type EterraSessionStatus = {
  connected: boolean;
  username?: string;
  connectedAt?: string;
  activeJobCount: number;
  eterraAvailable?: boolean;
  eterraMaintenance?: boolean;
  eterraHealthMessage?: string;
};

type GisStats = {
  totalUats: number;
  totalFeatures: number;
  totalTerenuri: number;
  totalCladiri: number;
  totalEnriched: number;
  totalNoGeom: number;
  countiesWithData: number;
  lastSyncAt: string | null;
  dbSizeMb: number | null;
};

export default function MonitorPage() {
  const [data, setData] = useState<MonitorData | null>(null);
  const [loading, setLoading] = useState(true);
  const [actionLoading, setActionLoading] = useState("");
  const [logs, setLogs] = useState<{ time: string; type: "info" | "ok" | "error" | "wait"; msg: string }[]>([]);
  const [counties, setCounties] = useState<string[]>([]);
  const [selectedCounty, setSelectedCounty] = useState("");
  const [eterraSession, setEterraSession] = useState<EterraSessionStatus>({ connected: false, activeJobCount: 0 });
  const [eterraConnecting, setEterraConnecting] = useState(false);
  const [showLoginForm, setShowLoginForm] = useState(false);
  const [eterraUser, setEterraUser] = useState("");
  const [eterraPwd, setEterraPwd] = useState("");
  const [gisStats, setGisStats] = useState<GisStats | null>(null);
  const rebuildPrevRef = useRef<string | null>(null);
  const pollRef = useRef<ReturnType<typeof setInterval> | null>(null);

  const refresh = useCallback(async () => {
    setLoading(true);
    try {
      const res = await fetch("/api/geoportal/monitor");
      if (res.ok) setData(await res.json());
    } catch { /* noop */ }
    setLoading(false);
  }, []);

  useEffect(() => { refresh(); }, [refresh]);

  // Auto-refresh every 30s
  useEffect(() => {
    const interval = setInterval(refresh, 30_000);
    return () => clearInterval(interval);
  }, [refresh]);

  const addLog = useCallback((type: "info" | "ok" | "error" | "wait", msg: string) => {
    setLogs((prev) => [{ time: new Date().toLocaleTimeString("ro-RO"), type, msg }, ...prev.slice(0, 49)]);
  }, []);

  // Fetch counties for sync selector
  useEffect(() => {
    fetch("/api/eterra/counties")
      .then((r) => (r.ok ? r.json() : Promise.reject()))
      .then((d: { counties: string[] }) => setCounties(d.counties ?? []))
      .catch(() => {});
  }, []);

  // eTerra session status — poll every 30s
  const fetchEterraSession = useCallback(async () => {
    try {
      const res = await fetch("/api/eterra/session");
      if (res.ok) setEterraSession(await res.json() as EterraSessionStatus);
    } catch { /* noop */ }
  }, []);

  useEffect(() => {
    void fetchEterraSession();
    const interval = setInterval(() => void fetchEterraSession(), 30_000);
    return () => clearInterval(interval);
  }, [fetchEterraSession]);

  // GIS stats — poll every 30s
  const fetchGisStats = useCallback(async () => {
    try {
      const res = await fetch("/api/eterra/stats");
      if (res.ok) setGisStats(await res.json() as GisStats);
    } catch { /* noop */ }
  }, []);

  useEffect(() => {
    void fetchGisStats();
    const interval = setInterval(() => void fetchGisStats(), 30_000);
    return () => clearInterval(interval);
  }, [fetchGisStats]);

  const handleEterraConnect = async () => {
    setEterraConnecting(true);
    try {
      const payload: Record<string, string> = { action: "connect" };
      if (eterraUser.trim()) payload.username = eterraUser.trim();
      if (eterraPwd.trim()) payload.password = eterraPwd.trim();
      const res = await fetch("/api/eterra/session", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(payload),
      });
      const d = await res.json() as { success?: boolean; error?: string };
      if (d.success) {
        await fetchEterraSession();
        addLog("ok", "eTerra conectat");
        setShowLoginForm(false);
        setEterraPwd("");
      } else {
        addLog("error", `eTerra: ${d.error ?? "Eroare conectare"}`);
      }
    } catch {
      addLog("error", "eTerra: eroare retea");
    }
    setEterraConnecting(false);
  };

  const handleEterraDisconnect = async () => {
    const res = await fetch("/api/eterra/session", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ action: "disconnect" }),
    });
    const d = await res.json() as { success?: boolean; error?: string };
    if (d.success) {
      setEterraSession({ connected: false, activeJobCount: 0 });
      addLog("info", "eTerra deconectat");
    } else {
      addLog("error", `Deconectare: ${d.error ?? "Eroare"}`);
    }
  };

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

  const triggerRebuild = async () => {
    setActionLoading("rebuild");
    addLog("info", "Se trimite webhook la N8N...");
    try {
      const res = await fetch("/api/geoportal/monitor", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ action: "rebuild" }),
      });
      const result = await res.json() as { ok?: boolean; error?: string; alreadyRunning?: boolean; previousPmtiles?: { lastModified: string } };
      if (!result.ok) {
        addLog("error", result.error ?? "Eroare necunoscuta");
        setActionLoading("");
        return;
      }
      addLog("ok", result.alreadyRunning
        ? "Rebuild deja in curs. Se monitorizeaza..."
        : "Webhook trimis. Rebuild pornit...");
      rebuildPrevRef.current = result.previousPmtiles?.lastModified ?? null;
      // Poll every 15s to check if PMTiles was updated
      if (pollRef.current) clearInterval(pollRef.current);
      pollRef.current = setInterval(async () => {
        try {
          const checkRes = await fetch("/api/geoportal/monitor", {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({ action: "check-rebuild", previousLastModified: rebuildPrevRef.current }),
          });
          const check = await checkRes.json() as { changed?: boolean; current?: { size: string; lastModified: string } };
          if (check.changed) {
            addLog("ok", `Rebuild finalizat! PMTiles: ${check.current?.size}, actualizat: ${check.current?.lastModified}`);
            if (pollRef.current) { clearInterval(pollRef.current); pollRef.current = null; }
            setActionLoading("");
            refresh();
          }
        } catch { /* continue polling */ }
      }, 15_000);
      // Timeout after 90 min (z18 builds can take 45-60 min)
      setTimeout(() => {
        if (pollRef.current) {
          clearInterval(pollRef.current);
          pollRef.current = null;
          addLog("error", "Timeout: rebuild nu s-a finalizat in 90 minute");
          setActionLoading("");
        }
      }, 90 * 60_000);
    } catch {
      addLog("error", "Nu s-a putut trimite webhook-ul");
      setActionLoading("");
    }
  };

  const triggerWarmCache = async () => {
    setActionLoading("warm-cache");
    addLog("info", "Se incarca tile-uri in cache...");
    try {
      const res = await fetch("/api/geoportal/monitor", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ action: "warm-cache" }),
      });
      const result = await res.json() as { ok?: boolean; error?: string; total?: number; hits?: number; misses?: number; errors?: number; message?: string };
      if (result.ok) {
        addLog("ok", result.message ?? "Cache warming finalizat");
      } else {
        addLog("error", result.error ?? "Eroare");
      }
    } catch {
      addLog("error", "Eroare la warm cache");
    }
    setActionLoading("");
    setTimeout(refresh, 2000);
  };

  return (
    <div className="mx-auto max-w-5xl p-6 space-y-6">
      <div className="flex items-center justify-between">
        <div>
          <h1 className="text-2xl font-bold">Tile Infrastructure Monitor</h1>
          <p className="text-sm text-muted-foreground">
            {data?.timestamp ? `Ultima actualizare: ${new Date(data.timestamp).toLocaleTimeString("ro-RO")}` : "Se incarca..."}
          </p>
        </div>
        <button
          onClick={refresh}
          disabled={loading}
          className="px-4 py-2 rounded bg-primary text-primary-foreground text-sm hover:bg-primary/90 disabled:opacity-50"
        >
          {loading ? "..." : "Reincarca"}
        </button>
      </div>

      {/* Status Cards */}
      <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
        {/* Nginx Card */}
        <Card title="nginx Tile Cache">
          {data?.nginx?.error ? (
            <StatusBadge status="error" label={data.nginx.error} />
          ) : data?.nginx ? (
            <div className="space-y-2 text-sm">
              <StatusBadge status="ok" label="Online" />
              <div className="grid grid-cols-2 gap-1 mt-2">
                <Stat label="Conexiuni active" value={data.nginx.activeConnections} />
                <Stat label="Total requests" value={data.nginx.requests?.toLocaleString()} />
                <Stat label="Reading" value={data.nginx.reading} />
                <Stat label="Writing" value={data.nginx.writing} />
                <Stat label="Waiting" value={data.nginx.waiting} />
              </div>
            </div>
          ) : <Skeleton />}
        </Card>

        {/* Martin Card */}
        <Card title="Martin Tile Server">
          {data?.martin?.error ? (
            <StatusBadge status="error" label={data.martin.error} />
          ) : data?.martin ? (
            <div className="space-y-2 text-sm">
              <StatusBadge status="ok" label={`${data.martin.sourceCount} surse active`} />
              <div className="mt-2 space-y-1">
                {data.martin.sources?.map((s) => (
                  <span key={s} className="inline-block mr-1 mb-1 px-2 py-0.5 rounded bg-muted text-xs">{s}</span>
                ))}
              </div>
            </div>
          ) : <Skeleton />}
        </Card>

        {/* PMTiles Card */}
        <Card title="PMTiles Overview">
          {data?.pmtiles?.error ? (
            <StatusBadge status="error" label={data.pmtiles.error} />
          ) : data?.pmtiles?.status === "not configured" ? (
            <StatusBadge status="warn" label="Nu e configurat" />
          ) : data?.pmtiles ? (
            <div className="space-y-2 text-sm">
              <StatusBadge status="ok" label={data.pmtiles.size ?? "OK"} />
              <Stat label="Ultima modificare" value={data.pmtiles.lastModified} />
            </div>
          ) : <Skeleton />}
        </Card>
      </div>

      {/* Cache Test Results */}
      <Card title="Cache Test">
        {data?.cacheTests ? (
          <div className="overflow-x-auto">
            <table className="w-full text-sm">
              <thead>
                <tr className="border-b border-border text-left">
                  <th className="py-2 pr-4">Tile</th>
                  <th className="py-2 pr-4">HTTP</th>
                  <th className="py-2">Cache</th>
                </tr>
              </thead>
              <tbody>
                {data.cacheTests.map((t, i) => (
                  <tr key={i} className="border-b border-border/50">
                    <td className="py-2 pr-4 font-mono text-xs">{t.tile}</td>
                    <td className="py-2 pr-4">{t.status}</td>
                    <td className="py-2">
                      <span className={`px-2 py-0.5 rounded text-xs font-medium ${
                        t.cache === "HIT" ? "bg-green-500/20 text-green-400" :
                        t.cache === "MISS" ? "bg-yellow-500/20 text-yellow-400" :
                        "bg-red-500/20 text-red-400"
                      }`}>
                        {t.cache}
                      </span>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        ) : <Skeleton />}
      </Card>

      {/* eTerra Connection + Live Stats */}
      <div className="grid grid-cols-1 md:grid-cols-4 gap-4">
        {/* Connection card */}
        <Card title="Conexiune eTerra">
          <div className="space-y-3">
            <div className="flex items-center gap-2">
              <span className={`w-2.5 h-2.5 rounded-full shrink-0 ${
                eterraSession.eterraMaintenance ? "bg-yellow-400 animate-pulse" :
                eterraSession.connected ? "bg-green-400" : "bg-red-400"
              }`} />
              <span className="text-sm font-medium">
                {eterraSession.eterraMaintenance ? "Mentenanta" :
                 eterraSession.connected ? (eterraSession.username || "Conectat") : "Deconectat"}
              </span>
            </div>
            {eterraSession.connected && eterraSession.connectedAt && (
              <div className="text-xs text-muted-foreground">
                Conectat de la {new Date(eterraSession.connectedAt).toLocaleTimeString("ro-RO")}
              </div>
            )}
            {eterraSession.connected && eterraSession.activeJobCount > 0 && (
              <div className="flex items-center gap-1.5 text-xs">
                <span className="w-1.5 h-1.5 rounded-full bg-blue-400 animate-pulse" />
                <span>{eterraSession.activeJobCount} {eterraSession.activeJobCount === 1 ? "job activ" : "joburi active"}</span>
              </div>
            )}
            <div className="pt-1">
              {eterraSession.connected ? (
                <button
                  onClick={handleEterraDisconnect}
                  className="w-full text-xs px-3 py-1.5 rounded-md border border-border hover:bg-destructive/10 hover:text-destructive hover:border-destructive/30 transition-colors"
                >
                  Deconecteaza
                </button>
              ) : (
                <button
                  onClick={() => setShowLoginForm((v) => !v)}
                  className="w-full text-xs px-3 py-1.5 rounded-md border border-border hover:border-primary/50 hover:bg-primary/10 transition-colors"
                >
                  {showLoginForm ? "Anuleaza" : "Conecteaza"}
                </button>
              )}
            </div>
            {showLoginForm && !eterraSession.connected && (
              <div className="space-y-2 pt-1">
                <input
                  type="text"
                  value={eterraUser}
                  onChange={(e) => setEterraUser(e.target.value)}
                  className="h-8 w-full rounded-md border border-border bg-background px-2 text-sm"
                  placeholder="Utilizator eTerra"
                />
                <input
                  type="password"
                  value={eterraPwd}
                  onChange={(e) => setEterraPwd(e.target.value)}
                  onKeyDown={(e) => { if (e.key === "Enter") handleEterraConnect(); }}
                  className="h-8 w-full rounded-md border border-border bg-background px-2 text-sm"
                  placeholder="Parola"
                />
                <button
                  onClick={handleEterraConnect}
                  disabled={eterraConnecting || !eterraUser.trim() || !eterraPwd.trim()}
                  className="w-full h-8 rounded-md bg-primary text-primary-foreground text-xs hover:bg-primary/90 disabled:opacity-50"
                >
                  {eterraConnecting ? "Se conecteaza..." : "Login"}
                </button>
              </div>
            )}
          </div>
        </Card>

        {/* Live stats cards */}
        <StatCard
          label="UAT-uri"
          value={gisStats?.totalUats}
          sub={gisStats?.countiesWithData ? `din ${gisStats.countiesWithData} judete` : undefined}
        />
        <StatCard
          label="Parcele"
          value={gisStats?.totalTerenuri}
          sub={gisStats?.totalEnriched ? `${gisStats.totalEnriched.toLocaleString("ro-RO")} enriched` : undefined}
        />
        <StatCard
          label="Cladiri"
          value={gisStats?.totalCladiri}
          sub={gisStats?.dbSizeMb ? `DB: ${gisStats.dbSizeMb >= 1024 ? `${(gisStats.dbSizeMb / 1024).toFixed(1)} GB` : `${gisStats.dbSizeMb} MB`}` : undefined}
        />
      </div>

      {gisStats?.lastSyncAt && (
        <div className="text-xs text-muted-foreground text-right -mt-2">
          Ultimul sync: {new Date(gisStats.lastSyncAt).toLocaleString("ro-RO")} — auto-refresh 30s
        </div>
      )}

      {/* Actions */}
      <Card title="Actiuni">
        {/* Tile infrastructure actions */}
        <div className="space-y-4">
          <div>
            <h3 className="text-xs font-medium text-muted-foreground mb-2 uppercase tracking-wider">Tile-uri</h3>
            <div className="flex flex-wrap gap-3">
              <ActionButton
                label="Rebuild PMTiles"
                description="Regenereaza tile-urile overview din PostGIS (~45-60 min)"
                loading={actionLoading === "rebuild"}
                onClick={triggerRebuild}
              />
              <ActionButton
                label="Warm Cache"
                description="Pre-incarca tile-uri frecvente in nginx cache"
                loading={actionLoading === "warm-cache"}
                onClick={triggerWarmCache}
              />
            </div>
          </div>

          {/* Sync actions */}
          <div>
            <div className="flex items-center justify-between mb-2">
              <h3 className="text-xs font-medium text-muted-foreground uppercase tracking-wider">Sincronizare eTerra</h3>
              <a
                href="/sync-management"
                className="text-xs text-primary hover:underline"
              >
                Gestioneaza reguli sync
              </a>
            </div>
            <div className="flex flex-wrap gap-3">
              <SyncTestButton
                label="Sync All Romania"
                description={`Toate judetele (${gisStats?.countiesWithData ?? "?"} jud, ${gisStats?.totalUats ?? "?"} UAT) — poate dura ore`}
                siruta=""
                mode="base"
                includeNoGeometry={false}
                actionKey="sync-all-counties"
                actionLoading={actionLoading}
                setActionLoading={setActionLoading}
                addLog={addLog}
                pollRef={pollRef}
                customEndpoint="/api/eterra/sync-all-counties"
              />
              <SyncTestButton
                label="Refresh ALL UATs"
                description={`Delta sync pe toate ${gisStats?.totalUats ?? "?"} UAT-urile din DB`}
                siruta=""
                mode="base"
                includeNoGeometry={false}
                actionKey="refresh-all"
                actionLoading={actionLoading}
                setActionLoading={setActionLoading}
                addLog={addLog}
                pollRef={pollRef}
                customEndpoint="/api/eterra/refresh-all"
              />
              <SyncTestButton
                label="Test Delta — Cluj-Napoca"
                description="Parcele + cladiri existente, fara magic (54975)"
                siruta="54975"
                mode="base"
                includeNoGeometry={false}
                actionKey="delta-cluj-base"
                actionLoading={actionLoading}
                setActionLoading={setActionLoading}
                addLog={addLog}
                pollRef={pollRef}
              />
              <SyncTestButton
                label="Test Delta — Feleacu"
                description="Magic + no-geom, cu enrichment (57582)"
                siruta="57582"
                mode="magic"
                includeNoGeometry={true}
                actionKey="delta-feleacu-magic"
                actionLoading={actionLoading}
                setActionLoading={setActionLoading}
                addLog={addLog}
                pollRef={pollRef}
              />
            </div>
          </div>

          {/* County sync */}
          <div>
            <h3 className="text-xs font-medium text-muted-foreground mb-2 uppercase tracking-wider">Sync pe judet</h3>
            <div className="flex items-end gap-3">
              <select
                value={selectedCounty}
                onChange={(e) => setSelectedCounty(e.target.value)}
                className="h-9 w-52 rounded-md border border-border bg-background px-3 text-sm"
              >
                <option value="">Alege judet...</option>
                {counties.map((c) => (
                  <option key={c} value={c}>{c}</option>
                ))}
              </select>
              <SyncTestButton
                label={selectedCounty ? `Sync ${selectedCounty}` : "Sync Judet"}
                description="TERENURI + CLADIRI + INTRAVILAN pentru tot judetul"
                siruta=""
                mode="base"
                includeNoGeometry={false}
                actionKey="sync-county"
                actionLoading={actionLoading}
                setActionLoading={setActionLoading}
                addLog={addLog}
                pollRef={pollRef}
                customEndpoint="/api/eterra/sync-county"
                customBody={{ county: selectedCounty }}
                disabled={!selectedCounty}
              />
            </div>
          </div>
        </div>
      </Card>

      {/* Activity Log */}
      {logs.length > 0 && (
        <div className="rounded-lg border border-border bg-card overflow-hidden">
          <div className="flex items-center justify-between px-4 py-2 bg-muted/50 border-b border-border">
            <span className="text-xs font-medium text-muted-foreground uppercase tracking-wider">Log activitate</span>
            <button onClick={() => setLogs([])} className="text-xs text-muted-foreground hover:text-foreground transition-colors">Sterge</button>
          </div>
          <div className="max-h-56 overflow-y-auto">
            {logs.map((log, i) => (
              <div key={i} className="flex items-start gap-2 px-4 py-1.5 text-xs border-b border-border/30 last:border-0">
                <span className="text-muted-foreground shrink-0 font-mono">{log.time}</span>
                <span className={`shrink-0 ${
                  log.type === "ok" ? "text-green-400" :
                  log.type === "error" ? "text-red-400" :
                  log.type === "wait" ? "text-yellow-400" :
                  "text-blue-400"
                }`}>
                  {log.type === "ok" ? "[OK]" : log.type === "error" ? "[ERR]" : log.type === "wait" ? "[...]" : "[i]"}
                </span>
                <span>{log.msg}</span>
              </div>
            ))}
          </div>
        </div>
      )}

      {/* Config */}
      <Card title="Configuratie">
        {data?.config ? (
          <div className="space-y-1 text-sm font-mono">
            <div><span className="text-muted-foreground">MARTIN_URL:</span> {data.config.martinUrl}</div>
            <div><span className="text-muted-foreground">PMTILES_URL:</span> {data.config.pmtilesUrl}</div>
            <div><span className="text-muted-foreground">N8N_WEBHOOK:</span> {data.config.n8nWebhook}</div>
          </div>
        ) : <Skeleton />}
      </Card>
    </div>
  );
}

/* ---- Sub-components ---- */

function Card({ title, children }: { title: string; children: React.ReactNode }) {
  return (
    <div className="rounded-lg border border-border bg-card p-4">
      <h2 className="text-sm font-semibold text-muted-foreground mb-3">{title}</h2>
      {children}
    </div>
  );
}

function StatusBadge({ status, label }: { status: "ok" | "error" | "warn"; label: string }) {
  const colors = {
    ok: "bg-green-500/20 text-green-400",
    error: "bg-red-500/20 text-red-400",
    warn: "bg-yellow-500/20 text-yellow-400",
  };
  return (
    <span className={`inline-flex items-center gap-1.5 px-2 py-1 rounded text-xs font-medium ${colors[status]}`}>
      <span className={`w-2 h-2 rounded-full ${status === "ok" ? "bg-green-400" : status === "error" ? "bg-red-400" : "bg-yellow-400"}`} />
      {label}
    </span>
  );
}

function Stat({ label, value }: { label: string; value?: string | number | null }) {
  return (
    <div>
      <div className="text-muted-foreground text-xs">{label}</div>
      <div className="font-medium">{value ?? "-"}</div>
    </div>
  );
}

function Skeleton() {
  return <div className="h-16 rounded bg-muted/50 animate-pulse" />;
}

function StatCard({ label, value, sub }: { label: string; value?: number | null; sub?: string }) {
  return (
    <div className="rounded-lg border border-border bg-card p-4">
      <div className="text-xs text-muted-foreground mb-1">{label}</div>
      <div className="text-2xl font-bold tabular-nums">
        {value != null ? value.toLocaleString("ro-RO") : <span className="text-muted-foreground">--</span>}
      </div>
      {sub && <div className="text-xs text-muted-foreground mt-1">{sub}</div>}
    </div>
  );
}

function ActionButton({ label, description, loading, onClick }: {
  label: string; description: string; loading: boolean; onClick: () => void;
}) {
  return (
    <button
      onClick={onClick}
      disabled={loading}
      className="flex flex-col items-start px-4 py-3 rounded-lg border border-border hover:border-primary/50 hover:bg-primary/5 transition-colors disabled:opacity-50 text-left"
    >
      <span className="font-medium text-sm">{loading ? "Se ruleaza..." : label}</span>
      <span className="text-xs text-muted-foreground">{description}</span>
    </button>
  );
}

function SyncTestButton({ label, description, siruta, mode, includeNoGeometry, actionKey, actionLoading, setActionLoading, addLog, pollRef, customEndpoint, customBody, disabled }: {
  label: string; description: string; siruta: string; mode: "base" | "magic";
  includeNoGeometry: boolean; actionKey: string; actionLoading: string;
  setActionLoading: (v: string) => void;
  addLog: (type: "info" | "ok" | "error" | "wait", msg: string) => void;
  pollRef: React.MutableRefObject<ReturnType<typeof setInterval> | null>;
  customEndpoint?: string;
  customBody?: Record<string, unknown>;
  disabled?: boolean;
}) {
  const startTimeRef = useRef<number>(0);
  const formatElapsed = () => {
    if (!startTimeRef.current) return "";
    const s = Math.round((Date.now() - startTimeRef.current) / 1000);
    return s < 60 ? `${s}s` : `${Math.floor(s / 60)}m${String(s % 60).padStart(2, "0")}s`;
  };

  return (
    <button
      onClick={async () => {
        setActionLoading(actionKey);
        startTimeRef.current = Date.now();
        addLog("info", `[${label}] Pornire...`);
        try {
          const endpoint = customEndpoint ?? "/api/eterra/sync-background";
          const body = customEndpoint ? (customBody ?? {}) : { siruta, mode, includeNoGeometry };
          const res = await fetch(endpoint, {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify(body),
          });
          const d = await res.json() as { jobId?: string; error?: string };
          if (!res.ok) {
            addLog("error", `[${label}] ${d.error ?? "Eroare start"}`);
            setActionLoading(""); return;
          }
          addLog("ok", `[${label}] Job: ${d.jobId?.slice(0, 8)}`);
          const jid = d.jobId;
          let lastPhase = "";
          if (pollRef.current) clearInterval(pollRef.current);
          pollRef.current = setInterval(async () => {
            try {
              const pr = await fetch(`/api/eterra/progress?jobId=${jid}`);
              const pg = await pr.json() as { status?: string; phase?: string; downloaded?: number; total?: number; note?: string; message?: string };
              const pct = pg.total ? Math.round(((pg.downloaded ?? 0) / pg.total) * 100) : 0;
              const elapsed = formatElapsed();
              const phaseChanged = pg.phase !== lastPhase;
              if (phaseChanged) lastPhase = pg.phase ?? "";
              // Only log phase changes and completion to keep log clean
              if (phaseChanged || pg.status === "done" || pg.status === "error") {
                const noteStr = pg.note ? ` — ${pg.note}` : "";
                addLog(
                  pg.status === "done" ? "ok" : pg.status === "error" ? "error" : "wait",
                  `[${label}] ${elapsed} | ${pg.phase ?? "..."} (${pct}%)${noteStr}`,
                );
              }
              if (pg.status === "done" || pg.status === "error") {
                const totalTime = formatElapsed();
                addLog(pg.status === "done" ? "ok" : "error",
                  `[${label}] TOTAL: ${totalTime}${pg.message ? " — " + pg.message : ""}`,
                );
                if (pollRef.current) { clearInterval(pollRef.current); pollRef.current = null; }
                setActionLoading("");
              }
            } catch { /* continue */ }
          }, 3000);
          setTimeout(() => {
            if (pollRef.current) {
              clearInterval(pollRef.current); pollRef.current = null;
              addLog("error", `[${label}] Timeout 3h (${formatElapsed()})`);
              setActionLoading("");
            }
          }, 3 * 60 * 60_000);
        } catch { addLog("error", `[${label}] Eroare retea`); setActionLoading(""); }
      }}
      disabled={!!actionLoading || !!disabled}
      className="flex flex-col items-start px-4 py-3 rounded-lg border border-border hover:border-primary/50 hover:bg-primary/5 transition-colors disabled:opacity-50 text-left"
    >
      <span className="font-medium text-sm">{actionLoading === actionKey ? "Se ruleaza..." : label}</span>
      <span className="text-xs text-muted-foreground">{description}</span>
    </button>
  );
}
