(() => {
  const { useState, useEffect, useRef, apiFetch, fmtDate } = window.DC;

  function MiniChart({ data, color = "#00e5ff", height = 40 }) {
    if (!data || data.length < 2) return <div style={{ height, background: "#080b10", borderRadius: 4 }} />;
    const max = Math.max(...data, 1);
    const points = data
      .map((value, index) => {
        const x = (index / (data.length - 1)) * 100;
        const y = height - (value / max) * height;
        return `${x},${y}`;
      })
      .join(" ");

    return (
      <svg width="100%" height={height} viewBox={`0 0 100 ${height}`} preserveAspectRatio="none" style={{ display: "block" }}>
        <polyline points={points} fill="none" stroke={color} strokeWidth="1.5" vectorEffect="non-scaling-stroke" />
        <polyline points={`0,${height} ${points} 100,${height}`} fill={color} fillOpacity="0.1" stroke="none" />
      </svg>
    );
  }

  function GaugeBar({ value, warn, crit, label, unit = "%" }) {
    const pct = Math.min(value || 0, 100);
    const color = pct >= crit ? "#f43f5e" : pct >= warn ? "#fbbf24" : "#22d3a5";
    return (
      <div style={{ marginBottom: 10 }}>
        <div style={{ display: "flex", justifyContent: "space-between", fontSize: 11, marginBottom: 4 }}>
          <span style={{ color: "#64748b" }}>{label}</span>
          <span style={{ color, fontWeight: 700 }}>
            {value?.toFixed(1)}
            {unit}
          </span>
        </div>
        <div style={{ background: "#131820", borderRadius: 4, height: 6, overflow: "hidden" }}>
          <div style={{ width: `${pct}%`, height: "100%", background: color, borderRadius: 4, transition: "width .5s ease" }} />
        </div>
      </div>
    );
  }

  function ServiceBadge({ name, status }) {
    const ok = status === "active";
    const color = ok ? "#22d3a5" : status === "unknown" ? "#64748b" : "#f43f5e";
    return (
      <div
        style={{
          display: "flex",
          alignItems: "center",
          gap: 5,
          padding: "4px 10px",
          background: `${color}12`,
          border: `1px solid ${color}30`,
          borderRadius: 20,
        }}
      >
        <div style={{ width: 6, height: 6, borderRadius: "50%", background: color }} />
        <span style={{ fontSize: 10, color }}>{name}</span>
      </div>
    );
  }

  function SectionHint({ children, tone = "#64748b" }) {
    return (
      <div
        style={{
          marginTop: 8,
          padding: "8px 10px",
          background: `${tone}10`,
          border: `1px solid ${tone}22`,
          borderRadius: 8,
          fontSize: 10,
          color: tone,
          lineHeight: 1.5,
        }}
      >
        {children}
      </div>
    );
  }

  function MetaChip({ children, color = "#64748b" }) {
    return (
      <span
        style={{
          fontSize: 9,
          color,
          border: `1px solid ${color}33`,
          background: `${color}12`,
          borderRadius: 999,
          padding: "2px 7px",
          lineHeight: 1.3,
        }}
      >
        {children}
      </span>
    );
  }

  function MonitorTabs({ tabs, activeTab, onChange }) {
    return (
      <div className="card" style={{ marginBottom: 14 }}>
        <div className="card-body" style={{ padding: 12 }}>
          <div className="nav-tabs-wrap settings-tabs-wrap internal-tabs-wrap">
            <div className="nav-tabs settings-tabs internal-tabs">
              {tabs.map((tab) => (
                <button
                  key={tab.key}
                  type="button"
                  onClick={() => onChange(tab.key)}
                  className={`nav-tab${activeTab === tab.key ? " active" : ""}`}
                  title={tab.label}
                >
                  <span className="nav-tab-icon" aria-hidden="true">{tab.icon}</span>
                  <span className="nav-tab-text">{tab.label}</span>
                </button>
              ))}
            </div>
          </div>
        </div>
      </div>
    );
  }

  function ServerMonitorCard({ server, onSelect, selected }) {
    const [metrics, setMetrics] = useState(null);
    const [loading, setLoading] = useState(false);
    const [error, setError] = useState(null);
    const [history, setHistory] = useState([]);
    const [expanded, setExpanded] = useState(false);
    const [sites, setSites] = useState(null);
    const [loadingSites, setLoadingSites] = useState(false);
    const [userProcs, setUserProcs] = useState([]);
    const intervalRef = useRef(null);
    const sitesIntervalRef = useRef(null);

    const syncUserProcs = (topProcsValue) => {
      if (!topProcsValue) {
        setUserProcs([]);
        return;
      }

      const lines = topProcsValue
        .split("\n")
        .filter(Boolean)
        .map((line) => {
          const parts = line.trim().split(/\s+/);
          return { name: parts[0], cpu: parseFloat(parts[1]) || 0, mem: parseFloat(parts[2]) || 0 };
        });
      setUserProcs(lines);
    };

    const fetchMetrics = async (force = false) => {
      setLoading(true);
      setError(null);
      try {
        const [metricsResponse, historyResponse] = await Promise.all([
          apiFetch(`/monitor/${server.id}${force ? "?refresh=1" : ""}`),
          apiFetch(`/monitor/${server.id}/history?limit=30`),
        ]);
        if (metricsResponse.error) setError(metricsResponse.error);
        else {
          setMetrics(metricsResponse);
          setHistory(Array.isArray(historyResponse) ? historyResponse : []);
          syncUserProcs(metricsResponse.top_procs);
        }
      } catch (err) {
        setError(err.message);
      }
      setLoading(false);
    };

    const fetchSites = async (force = false) => {
      setLoadingSites(true);
      try {
        const response = await apiFetch(`/monitor/${server.id}/sites${force ? "?refresh=1" : ""}`);
        setSites(Array.isArray(response) ? response : []);
      } catch {
        setSites([]);
      }
      setLoadingSites(false);
    };

    const refreshCard = async () => {
      await fetchMetrics(true);
      if (expanded) {
        await fetchSites(true);
      }
    };

    useEffect(() => {
      fetchMetrics();
      intervalRef.current = setInterval(fetchMetrics, 60000);
      return () => {
        clearInterval(intervalRef.current);
        clearInterval(sitesIntervalRef.current);
      };
    }, [server.id]);

    useEffect(() => {
      clearInterval(sitesIntervalRef.current);

      if (!expanded) {
        return undefined;
      }

      fetchSites();
      sitesIntervalRef.current = setInterval(() => fetchSites(), 60000);

      return () => clearInterval(sitesIntervalRef.current);
    }, [expanded, server.id]);

    const statusColor = { ok: "#22d3a5", warning: "#fbbf24", critical: "#f43f5e" };
    const statusIcon = { ok: "●", warning: "⚠", critical: "✗" };
    const status = metrics?.status || (error ? "critical" : "ok");
    const isSelected = selected === server.id;
    const borderColor = isSelected
      ? "#00e5ff"
      : metrics?.status === "critical"
        ? "#f43f5e33"
        : metrics?.status === "warning"
          ? "#fbbf2433"
          : "#1e2a3a";

    const loadDetail = async () => {
      if (expanded) {
        setExpanded(false);
        return;
      }

      setExpanded(true);
      syncUserProcs(metrics?.top_procs);
    };

    return (
      <div className="server-card" style={{ borderColor, boxShadow: isSelected ? "0 0 0 1px #00e5ff22" : "none" }}>
        <div className="server-header" style={{ flexWrap: "wrap", gap: 8 }}>
          <div
            style={{
              width: 10,
              height: 10,
              borderRadius: "50%",
              background: statusColor[status],
              boxShadow: `0 0 8px ${statusColor[status]}`,
              flexShrink: 0,
            }}
          />
          <div className="server-info" onClick={() => onSelect?.(server.id)} style={{ cursor: "pointer" }}>
            <div style={{ display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" }}>
              <span className="server-name">{server.label}</span>
              <span
                className="tag"
                style={{
                  borderColor: `${statusColor[status]}44`,
                  color: statusColor[status],
                  background: `${statusColor[status]}15`,
                  fontSize: 9,
                }}
              >
                {statusIcon[status]} {status.toUpperCase()}
              </span>
            </div>
            <div className="server-host">{server.host}</div>
          </div>
          {loading && <span style={{ fontSize: 10, color: "#64748b", animation: "pulse 1s infinite" }}>actualizando...</span>}
          <button
            onClick={(event) => {
              event.stopPropagation();
              onSelect?.(server.id);
            }}
            className="btn btn-ghost btn-sm"
            style={{ color: isSelected ? "#00e5ff" : "#64748b" }}
            title="Ver detalle"
          >
            ⌁
          </button>
          <button
            onClick={(event) => {
              event.stopPropagation();
              refreshCard();
            }}
            className="btn btn-ghost btn-sm"
            style={{ marginLeft: "auto" }}
            title={expanded ? "Actualizar métricas y sitios" : "Actualizar métricas"}
          >
            ↻
          </button>
        </div>

        {error && (
          <div style={{ padding: "10px 16px", background: "#f43f5e10", borderTop: "1px solid #f43f5e22", fontSize: 11, color: "#f43f5e" }}>
            ✗ {error}
          </div>
        )}

        {metrics && !error && (
          <div style={{ padding: "12px 16px", borderTop: "1px solid #1e2a3a22" }}>
            <div style={{ display: "grid", gridTemplateColumns: "repeat(4,1fr)", gap: 8, marginBottom: 12 }}>
              {[
                { label: "CPU", value: metrics.cpu_pct, warn: 70, crit: 90 },
                { label: "RAM", value: metrics.ram_pct, warn: 75, crit: 90 },
                { label: "Disco", value: metrics.disk_pct, warn: 80, crit: 95 },
                { label: "Load", value: parseFloat(metrics.load_avg?.split(" ")[0]), warn: 2, crit: 4, unit: "" },
              ].map((item) => {
                const color =
                  item.value >= (item.crit || 99) ? "#f43f5e" : item.value >= (item.warn || 80) ? "#fbbf24" : "#22d3a5";
                return (
                  <div key={item.label} style={{ background: "#080b10", borderRadius: 8, padding: "8px 10px", textAlign: "center" }}>
                    <div style={{ fontSize: 16, fontWeight: 800, color, fontFamily: "Syne,sans-serif" }}>
                      {item.value?.toFixed(0)}
                      {item.unit ?? "%"}
                    </div>
                    <div style={{ fontSize: 9, color: "#64748b", marginTop: 2 }}>{item.label}</div>
                  </div>
                );
              })}
            </div>

            {history.length > 2 && (
              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8, marginBottom: 12 }}>
                {[
                  { label: "CPU %", data: history.map((entry) => entry.cpu_pct), color: "#00e5ff" },
                  { label: "RAM %", data: history.map((entry) => entry.ram_pct), color: "#a78bfa" },
                ].map((chart) => (
                  <div key={chart.label} style={{ background: "#080b10", borderRadius: 8, padding: "8px 10px" }}>
                    <div style={{ fontSize: 9, color: "#64748b", marginBottom: 4 }}>{chart.label}</div>
                    <MiniChart data={chart.data} color={chart.color} height={35} />
                  </div>
                ))}
              </div>
            )}

            <div style={{ display: "flex", gap: 6, flexWrap: "wrap", marginBottom: 10 }}>
              <ServiceBadge name="Apache" status={metrics.apache} />
              <ServiceBadge name="PHP-FPM" status={metrics.php_fpm} />
              <ServiceBadge name="MariaDB" status={metrics.mariadb} />
              <ServiceBadge name="DNS" status={metrics.dns_ok ? "active" : "inactive"} />
            </div>

            <SectionHint>
              Fuente: lectura directa por SSH al servidor con <code>top</code>, <code>free</code>, <code>df</code>, <code>systemctl</code>,
              <code> dig</code> y <code>ps</code>.
            </SectionHint>

            <div style={{ display: "flex", gap: 12, fontSize: 10, color: "#64748b", flexWrap: "wrap" }}>
              <span>💾 {metrics.disk_used}/{metrics.disk_total}</span>
              <span>🕐 {metrics.uptime?.replace("up ", "")}</span>
              <span>⚡ Load: {metrics.load_avg}</span>
            </div>

            {metrics.alerts?.length > 0 && (
              <div style={{ marginTop: 10, display: "flex", flexDirection: "column", gap: 4 }}>
                {metrics.alerts.map((alert, index) => (
                  <div key={index} className="alert alert-danger" style={{ marginBottom: 0, padding: "6px 10px", fontSize: 11 }}>
                    ⚠ {alert}
                  </div>
                ))}
              </div>
            )}

            <button
              onClick={loadDetail}
              style={{
                marginTop: 10,
                width: "100%",
                background: "#131820",
                border: "1px solid #1e2a3a22",
                borderRadius: 8,
                padding: "6px",
                fontSize: 11,
                color: "#64748b",
                cursor: "pointer",
              }}
            >
              {expanded ? "▲ Ocultar detalle" : "▼ Ver sitios y procesos"}
            </button>
          </div>
        )}

        {expanded && (
          <div style={{ borderTop: "1px solid #1e2a3a33", padding: "12px 16px", background: "#080b10" }}>
            <div style={{ marginBottom: 14 }}>
              <div
                style={{
                  fontSize: 10,
                  color: "#64748b",
                  letterSpacing: "1px",
                  textTransform: "uppercase",
                  fontWeight: 700,
                  marginBottom: 8,
                  display: "flex",
                  justifyContent: "space-between",
                  alignItems: "center",
                  gap: 8,
                }}
              >
                <span>🌐 Estado de sitios ({sites?.length || 0})</span>
                <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                  {loadingSites && <span style={{ color: "#00e5ff", animation: "pulse 1s infinite" }}>verificando...</span>}
                  <button
                    onClick={() => fetchSites(true)}
                    disabled={loadingSites}
                    className="btn btn-ghost btn-sm"
                    title="Verificar sitios ahora"
                  >
                    {loadingSites ? "⟳" : "↻"}
                  </button>
                </div>
              </div>
              <SectionHint tone="#00e5ff">
                Fuente: se hace una petición HTTPS real a <code>https://dominio/intranet/</code>. El tiempo mostrado es la demora de ese check;
                si aparece <strong>timeout</strong>, el valor es el tiempo hasta abortar la prueba. Además se valida DNS por lookup y SSL por
                TLS en el puerto 443.
              </SectionHint>
              {sites && sites.length > 0 ? (
                <div style={{ display: "flex", flexDirection: "column", gap: 4 }}>
                  {sites.map((site, index) => {
                    const siteColor =
                      {
                        ok: "#22d3a5",
                        slow: "#fbbf24",
                        slow_critical: "#f43f5e",
                        down: "#f43f5e",
                        timeout: "#f43f5e",
                        error: "#f43f5e",
                      }[site.status] || "#64748b";

                    const siteIcon =
                      {
                        ok: "✅",
                        slow: "⚠️",
                        slow_critical: "🔴",
                        down: "🔴",
                        timeout: "⏱",
                        error: "❌",
                      }[site.status] || "•";

                    return (
                      <div
                        key={index}
                        style={{
                          display: "flex",
                          alignItems: "center",
                          gap: 8,
                          padding: "6px 10px",
                          background: "#0d1017",
                          borderRadius: 8,
                          flexWrap: "wrap",
                        }}
                      >
                        <span style={{ fontSize: 12, flexShrink: 0 }}>{siteIcon}</span>
                        <a
                          href={`https://${site.domain}/intranet/`}
                          target="_blank"
                          rel="noreferrer"
                          style={{
                            flex: 1,
                            minWidth: 100,
                            fontSize: 11,
                            color: "#00e5ff",
                            textDecoration: "none",
                            overflow: "hidden",
                            textOverflow: "ellipsis",
                            whiteSpace: "nowrap",
                          }}
                        >
                          {site.domain}
                        </a>
                        <span style={{ fontSize: 10, color: "#64748b", flexShrink: 0 }}>{site.virt_user}</span>
                        <span
                          style={{
                            fontSize: 11,
                            color: site.response_ms > 5000 ? "#f43f5e" : site.response_ms > 2000 ? "#fbbf24" : "#64748b",
                            flexShrink: 0,
                            fontWeight: 700,
                          }}
                        >
                          {site.response_ms}ms
                        </span>
                        <span className="tag" style={{ borderColor: `${siteColor}44`, color: siteColor, background: `${siteColor}15`, fontSize: 9 }}>
                          {site.status}
                        </span>
                        <div style={{ width: "100%", display: "flex", gap: 6, flexWrap: "wrap", paddingLeft: 20 }}>
                          <MetaChip color="#00e5ff">HTTPS /intranet/</MetaChip>
                          {site.http_status > 0 && <MetaChip>HTTP {site.http_status}</MetaChip>}
                          <MetaChip color={site.dns_ok ? "#22d3a5" : "#f43f5e"}>DNS {site.dns_ok ? "ok" : "fail"}</MetaChip>
                          <MetaChip color={Number.isFinite(site.ssl_valid_days) && site.ssl_valid_days <= 10 ? "#fbbf24" : "#64748b"}>
                            SSL {Number.isFinite(site.ssl_valid_days) ? `${site.ssl_valid_days}d` : "n/d"}
                          </MetaChip>
                          {site.checked_at && <MetaChip>{fmtDate(site.checked_at)}</MetaChip>}
                        </div>
                      </div>
                    );
                  })}
                </div>
              ) : (
                !loadingSites && <div style={{ fontSize: 11, color: "#475569" }}>Sin dominios configurados</div>
              )}
            </div>

            {userProcs.length > 0 && (
              <div>
                <div
                  style={{
                    fontSize: 10,
                    color: "#64748b",
                    letterSpacing: "1px",
                    textTransform: "uppercase",
                    fontWeight: 700,
                    marginBottom: 8,
                  }}
                >
                  ⚡ Top procesos por consumo
                </div>
                <SectionHint>
                  Fuente: salida de <code>ps aux --sort=-%mem</code> tomada por SSH en el servidor al momento de la lectura.
                </SectionHint>
                <div style={{ background: "#0d1017", borderRadius: 8, overflow: "hidden" }}>
                  {userProcs.map((proc, index) => {
                    const cpuColor = proc.cpu > 50 ? "#f43f5e" : proc.cpu > 20 ? "#fbbf24" : "#22d3a5";
                    return (
                      <div
                        key={index}
                        style={{
                          display: "grid",
                          gridTemplateColumns: "1fr 60px 80px 60px 80px",
                          gap: 8,
                          padding: "7px 12px",
                          borderBottom: "1px solid #1e2a3a15",
                          alignItems: "center",
                          fontSize: 11,
                        }}
                      >
                        <span style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", color: "#e2e8f0" }}>{proc.name}</span>
                        <span style={{ color: cpuColor, fontWeight: 700, textAlign: "right" }}>{proc.cpu.toFixed(1)}%</span>
                        <div style={{ background: "#131820", borderRadius: 3, height: 4 }}>
                          <div style={{ width: `${Math.min(proc.cpu, 100)}%`, height: "100%", background: cpuColor, borderRadius: 3 }} />
                        </div>
                        <span style={{ color: "#a78bfa", fontWeight: 700, textAlign: "right" }}>{proc.mem.toFixed(1)}%</span>
                        <div style={{ background: "#131820", borderRadius: 3, height: 4 }}>
                          <div style={{ width: `${Math.min(proc.mem, 100)}%`, height: "100%", background: "#a78bfa", borderRadius: 3 }} />
                        </div>
                      </div>
                    );
                  })}
                </div>
              </div>
            )}
          </div>
        )}
      </div>
    );
  }

  function SitesPanel({ serverId }) {
    const [sites, setSites] = useState([]);
    const [loading, setLoading] = useState(false);
    const intervalRef = useRef(null);

    const check = async (force = false) => {
      setLoading(true);
      const response = await apiFetch(`/monitor/${serverId}/sites${force ? "?refresh=1" : ""}`);
      setSites(Array.isArray(response) ? response : []);
      setLoading(false);
    };

    useEffect(() => {
      check();
      intervalRef.current = setInterval(() => check(), 60000);
      return () => clearInterval(intervalRef.current);
    }, [serverId]);

    const statusColor = {
      ok: "#22d3a5",
      slow: "#fbbf24",
      slow_critical: "#f43f5e",
      down: "#f43f5e",
      timeout: "#f43f5e",
      error: "#f43f5e",
    };

    const statusIcon = {
      ok: "✅",
      slow: "⚠️",
      slow_critical: "🔴",
      down: "🔴",
      timeout: "⏱",
      error: "❌",
    };

    return (
        <div className="card">
          <div className="card-head">
            <span>🌐 Estado de sitios</span>
            <button onClick={() => check(true)} disabled={loading} className="btn btn-ghost btn-sm">
              {loading ? "⟳ Verificando..." : "↻ Verificar"}
            </button>
          </div>
          <div style={{ padding: "12px 16px 0" }}>
            <SectionHint tone="#00e5ff">
              Fuente: petición HTTPS a <code>https://dominio/intranet/</code>. El tiempo es lo que demora ese acceso desde el monitor; si cae en
              <strong> timeout</strong>, el valor se queda cerca del corte configurado. También se revisa DNS y certificado SSL.
            </SectionHint>
          </div>
        <div>
          {sites.length === 0 && !loading && (
            <div style={{ padding: "20px 16px", textAlign: "center", fontSize: 12, color: "#64748b" }}>
              Sin dominios configurados o aún no verificados
            </div>
          )}
          {sites.map((site, index) => (
            <div
              key={index}
              style={{
                padding: "10px 16px",
                display: "flex",
                alignItems: "center",
                gap: 10,
                borderBottom: "1px solid #1e2a3a15",
                flexWrap: "wrap",
              }}
            >
              <span style={{ fontSize: 14, flexShrink: 0 }}>{statusIcon[site.status] || "•"}</span>
              <a
                href={`https://${site.domain}/intranet/`}
                target="_blank"
                rel="noreferrer"
                style={{
                  flex: 1,
                  minWidth: 120,
                  fontSize: 12,
                  color: "#00e5ff",
                  textDecoration: "none",
                  overflow: "hidden",
                  textOverflow: "ellipsis",
                  whiteSpace: "nowrap",
                }}
              >
                {site.domain}
              </a>
              <span
                className="tag"
                style={{
                  borderColor: `${statusColor[site.status] || "#64748b"}44`,
                  color: statusColor[site.status] || "#64748b",
                  background: `${statusColor[site.status] || "#64748b"}15`,
                }}
              >
                {site.status}
              </span>
              <span style={{ fontSize: 11, color: site.response_ms > 2000 ? "#fbbf24" : "#64748b", flexShrink: 0 }}>
                {site.response_ms}ms
              </span>
              <div style={{ width: "100%", display: "flex", gap: 6, flexWrap: "wrap", paddingLeft: 24 }}>
                <MetaChip color="#00e5ff">HTTPS /intranet/</MetaChip>
                {site.http_status > 0 && <MetaChip>HTTP {site.http_status}</MetaChip>}
                <MetaChip color={site.dns_ok ? "#22d3a5" : "#f43f5e"}>DNS {site.dns_ok ? "ok" : "fail"}</MetaChip>
                <MetaChip color={Number.isFinite(site.ssl_valid_days) && site.ssl_valid_days <= 10 ? "#fbbf24" : "#64748b"}>
                  SSL {Number.isFinite(site.ssl_valid_days) ? `${site.ssl_valid_days}d` : "n/d"}
                </MetaChip>
                {site.checked_at && <MetaChip>{fmtDate(site.checked_at)}</MetaChip>}
              </div>
            </div>
          ))}
        </div>
      </div>
    );
  }

  function TopProcsPanel({ procs }) {
    if (!procs) return null;
    const lines = procs.split("\n").filter(Boolean).map((line) => {
      const parts = line.trim().split(/\s+/);
      return { name: parts[0], cpu: parseFloat(parts[1]) || 0, mem: parseFloat(parts[2]) || 0 };
    });
    if (!lines.length) return null;
    const maxCpu = Math.max(...lines.map((line) => line.cpu), 1);
    const maxMem = Math.max(...lines.map((line) => line.mem), 1);

    return (
      <div className="card">
        <div className="card-head">⚡ Top procesos</div>
        <div style={{ padding: "12px 16px 0" }}>
          <SectionHint>
            Fuente: salida de <code>ps aux --sort=-%mem</code> tomada por SSH en el servidor seleccionado.
          </SectionHint>
        </div>
        <div style={{ overflowX: "auto" }}>
          <table style={{ width: "100%", borderCollapse: "collapse", fontSize: 11 }}>
            <thead>
              <tr style={{ background: "#131820" }}>
                {["Proceso", "CPU %", "", "MEM %", ""].map((header, index) => (
                  <th
                    key={index}
                    style={{
                      padding: "6px 12px",
                      color: "#64748b",
                      textAlign: index === 0 ? "left" : "right",
                      fontSize: 9,
                      letterSpacing: "1px",
                      whiteSpace: "nowrap",
                    }}
                  >
                    {header}
                  </th>
                ))}
              </tr>
            </thead>
            <tbody>
              {lines.map((proc, index) => (
                <tr key={index} style={{ borderBottom: "1px solid #1e2a3a15" }}>
                  <td
                    style={{
                      padding: "8px 12px",
                      color: "#e2e8f0",
                      fontFamily: "JetBrains Mono,monospace",
                      maxWidth: 150,
                      overflow: "hidden",
                      textOverflow: "ellipsis",
                      whiteSpace: "nowrap",
                    }}
                  >
                    {proc.name}
                  </td>
                  <td
                    style={{
                      padding: "8px 6px",
                      textAlign: "right",
                      color: proc.cpu > 50 ? "#f43f5e" : proc.cpu > 20 ? "#fbbf24" : "#22d3a5",
                      fontWeight: 700,
                    }}
                  >
                    {proc.cpu.toFixed(1)}
                  </td>
                  <td style={{ padding: "8px 12px 8px 4px", width: 80 }}>
                    <div style={{ background: "#131820", borderRadius: 3, height: 4 }}>
                      <div
                        style={{
                          width: `${(proc.cpu / maxCpu) * 100}%`,
                          height: "100%",
                          background: proc.cpu > 50 ? "#f43f5e" : proc.cpu > 20 ? "#fbbf24" : "#22d3a5",
                          borderRadius: 3,
                        }}
                      />
                    </div>
                  </td>
                  <td
                    style={{
                      padding: "8px 6px",
                      textAlign: "right",
                      color: proc.mem > 50 ? "#f43f5e" : proc.mem > 20 ? "#fbbf24" : "#a78bfa",
                      fontWeight: 700,
                    }}
                  >
                    {proc.mem.toFixed(1)}
                  </td>
                  <td style={{ padding: "8px 12px 8px 4px", width: 80 }}>
                    <div style={{ background: "#131820", borderRadius: 3, height: 4 }}>
                      <div
                        style={{
                          width: `${(proc.mem / maxMem) * 100}%`,
                          height: "100%",
                          background: "#a78bfa",
                          borderRadius: 3,
                        }}
                      />
                    </div>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
    );
  }

  function MonitorView({ servers }) {
    const [selected, setSelected] = useState(null);
    const [detailMetrics, setDetail] = useState(null);
    const [detailHistory, setDetailHistory] = useState([]);
    const [alerts, setAlerts] = useState([]);
    const [activeTab, setActiveTab] = useState(() => {
      try {
        return window.localStorage.getItem("dc:tabs:monitor") || "servers";
      } catch (_error) {
        return "servers";
      }
    });

    useEffect(() => {
      apiFetch("/monitor/alerts").then((data) => setAlerts(Array.isArray(data) ? data : []));
    }, []);

    useEffect(() => {
      if (!selected) {
        setDetail(null);
        setDetailHistory([]);
        return;
      }
      apiFetch(`/monitor/${selected}`).then((data) => setDetail(data));
      apiFetch(`/monitor/${selected}/history?limit=60`).then((data) => setDetailHistory(Array.isArray(data) ? data : []));
      setActiveTab("detail");
    }, [selected]);

    const tabs = [
      { key: "servers", label: "Servidores", icon: "🖥" },
      { key: "detail", label: "Detalle", icon: "📊" },
      { key: "alerts", label: "Alertas", icon: "🔔" },
    ];

    useEffect(() => {
      if (!tabs.some((tab) => tab.key === activeTab)) {
        setActiveTab("servers");
      }
    }, [activeTab, tabs]);

    useEffect(() => {
      try {
        window.localStorage.setItem("dc:tabs:monitor", activeTab);
      } catch (_error) {}
    }, [activeTab]);

    return (
      <div style={{ animation: "fadeIn .3s ease" }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 14, flexWrap: "wrap", gap: 8 }}>
          <div>
            <div style={{ fontFamily: "Syne,sans-serif", fontWeight: 800, fontSize: 20 }}>Monitor</div>
            <div style={{ fontSize: 11, color: "#64748b", marginTop: 2 }}>
              {servers.length} servidores · actualización automática cada 60s
            </div>
          </div>
          {alerts.filter((alert) => !alert.sent_email).length > 0 && (
            <span className="tag" style={{ borderColor: "#f43f5e44", color: "#f43f5e", background: "#f43f5e15" }}>
              🔔 {alerts.length} alerta{alerts.length > 1 ? "s" : ""}
            </span>
          )}
        </div>

        <MonitorTabs tabs={tabs} activeTab={activeTab} onChange={setActiveTab} />

        {activeTab === "servers" && (
          <div style={{ display: "flex", flexDirection: "column", gap: 10, marginBottom: 20 }}>
            {servers.map((server) => (
              <ServerMonitorCard key={server.id} server={server} selected={selected} onSelect={setSelected} />
            ))}
          </div>
        )}

        {activeTab === "detail" && (
          selected && detailMetrics && !detailMetrics.error ? (
            <div style={{ animation: "fadeIn .2s ease" }}>
              <div style={{ fontFamily: "Syne,sans-serif", fontWeight: 800, fontSize: 16, marginBottom: 12 }}>
                📊 Detalle — {servers.find((server) => server.id === selected)?.label}
              </div>

              <div className="card">
                <div className="card-head">📈 Métricas detalladas</div>
                <div className="card-body">
                  <GaugeBar value={detailMetrics.cpu_pct} warn={70} crit={90} label="CPU" />
                  <GaugeBar
                    value={detailMetrics.ram_pct}
                    warn={75}
                    crit={90}
                    label={`RAM (${detailMetrics.ram_used?.toFixed(0)}MB / ${detailMetrics.ram_total?.toFixed(0)}MB)`}
                  />
                  <GaugeBar
                    value={detailMetrics.disk_pct}
                    warn={80}
                    crit={95}
                    label={`Disco (${detailMetrics.disk_used} / ${detailMetrics.disk_total})`}
                  />
                  <SectionHint>
                    Fuente: lectura por SSH del servidor actual. CPU, RAM, disco, servicios y DNS salen de comandos del sistema en tiempo real.
                  </SectionHint>
                </div>
              </div>

              {detailHistory.length > 2 && (
                <div className="card">
                  <div className="card-head">📉 Historial (últimas {detailHistory.length} lecturas)</div>
                  <div className="card-body">
                    <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
                      {[
                        { label: "CPU %", data: detailHistory.map((entry) => entry.cpu_pct), color: "#00e5ff" },
                        { label: "RAM %", data: detailHistory.map((entry) => entry.ram_pct), color: "#a78bfa" },
                        { label: "Disco %", data: detailHistory.map((entry) => entry.disk_pct), color: "#fbbf24" },
                        {
                          label: "Load avg",
                          data: detailHistory.map((entry) => parseFloat(entry.load_avg?.split(" ")[0]) || 0),
                          color: "#22d3a5",
                        },
                      ].map((chart) => (
                        <div key={chart.label} style={{ background: "#080b10", borderRadius: 8, padding: "10px 12px" }}>
                          <div style={{ fontSize: 10, color: "#64748b", marginBottom: 6, display: "flex", justifyContent: "space-between" }}>
                            <span>{chart.label}</span>
                            <span style={{ color: chart.color }}>{chart.data[chart.data.length - 1]?.toFixed(1)}</span>
                          </div>
                          <MiniChart data={chart.data} color={chart.color} height={50} />
                        </div>
                      ))}
                    </div>
                    <SectionHint>
                      Fuente: snapshots históricos guardados por el monitor en cada barrido automático o actualización manual.
                    </SectionHint>
                  </div>
                </div>
              )}

              <TopProcsPanel procs={detailMetrics.top_procs} />
              <SitesPanel serverId={selected} />
            </div>
          ) : (
            <div className="card">
              <div className="card-head">📊 Detalle del servidor</div>
              <div className="card-body" style={{ color: "#94a3b8", fontSize: 12 }}>
                Selecciona un servidor desde la pestaña <strong style={{ color: "#e2e8f0" }}>Servidores</strong> para ver métricas, procesos y sitios.
              </div>
            </div>
          )
        )}

        {activeTab === "alerts" && (
          <div className="card">
            <div className="card-head">🔔 Alertas recientes</div>
            <div style={{ padding: "12px 16px 0" }}>
              <SectionHint>
                Fuente: alertas generadas por el monitor cuando detecta caídas, lentitud, presión de recursos o sitios degradados.
              </SectionHint>
            </div>
            <div>
              {alerts.slice(0, 10).map((alert, index) => (
                <div
                  key={index}
                  style={{
                    padding: "10px 16px",
                    borderBottom: "1px solid #1e2a3a15",
                    display: "flex",
                    gap: 10,
                    alignItems: "flex-start",
                    flexWrap: "wrap",
                  }}
                >
                  <span style={{ fontSize: 14, flexShrink: 0 }}>
                    {alert.type === "critical" ? "🔴" : alert.type === "site_down" ? "🔴" : "⚠️"}
                  </span>
                  <div style={{ flex: 1, minWidth: 100 }}>
                    <div style={{ fontSize: 12, fontWeight: 700 }}>{alert.server_label}</div>
                    <div style={{ fontSize: 11, color: "#64748b", marginTop: 2, whiteSpace: "pre-wrap" }}>{alert.message}</div>
                  </div>
                  <span style={{ fontSize: 10, color: "#475569", flexShrink: 0 }}>{fmtDate(alert.created_at)}</span>
                </div>
              ))}
            </div>
          </div>
        )}
      </div>
    );
  }

  window.DCViews.MonitorView = MonitorView;
})();
