// dashboard-column-3-queues-active-campaig.js — extracted verbatim from dashboard.js (pure move).

// ── COLUMN 3 — QUEUES + ACTIVE CAMPAIGNS ────────────────────────
function renderLiveMapQueuesAndCampaigns(data) {
  const q = data.queues || {};
  const c = data.campaigns || {};

  const col = el("div", {
    style: "display:flex;flex-direction:column;gap:10px;max-height:75vh;overflow-y:auto;",
  });

  // Queues — horizontal stacked bars
  col.appendChild(
    el("div", { class: "card", style: "padding:12px;" }, [
      el(
        "div",
        { class: "wizard-section-title", style: "margin-bottom:10px;" },
        "Background queues",
      ),
      queueBar(
        "Enrichment",
        [
          { label: "pending", value: q.enrichment?.pending || 0, color: "var(--text-3)" },
          { label: "running", value: q.enrichment?.running || 0, color: "var(--blue)" },
          { label: "failed", value: q.enrichment?.failed || 0, color: "var(--red)" },
          { label: "done 24h", value: q.enrichment?.completed_24h || 0, color: "var(--green)" },
        ],
        trendFromHistory((s) => s.enrichPending),
        // Click any segment to open the enrichment drawer pre-focused on that
        // status. Clicking the label or empty area defaults to "completed" —
        // answers the operator question "which contacts/companies got enriched?".
        {
          onLabelClick: () => openEnrichmentDrawer("completed"),
          onSegmentClick: (segLabel) => {
            const map = {
              pending: "pending",
              running: "running",
              failed: "failed",
              "done 24h": "completed",
            };
            openEnrichmentDrawer(map[segLabel] || "completed");
          },
        },
      ),
      queueBar(
        "Sequences",
        [
          { label: "active", value: q.sequences?.active || 0, color: "var(--blue)" },
          { label: "replied", value: q.sequences?.replied || 0, color: "var(--green)" },
          { label: "completed", value: q.sequences?.completed || 0, color: "var(--text-3)" },
          { label: "paused", value: q.sequences?.paused || 0, color: "var(--yellow)" },
        ],
        trendFromHistory((s) => s.seqActive),
      ),
      queueBar(
        "Commands",
        [
          { label: "pending", value: q.commands?.pending || 0, color: "var(--text-3)" },
          { label: "in-progress", value: q.commands?.in_progress || 0, color: "var(--blue)" },
        ],
        null,
      ),
    ]),
  );

  // 🔑 API key health — only renders when at least one rotator has been
  // instantiated (i.e. a scraper has run since boot).
  if (data.apiKeys && Object.keys(data.apiKeys).length > 0) {
    col.appendChild(renderApiKeyHealth(data.apiKeys));
  }

  // 🗓 Activity heatmap — 7 days × 24 hours, coloured by event count
  col.appendChild(renderActivityHeatmap(data));

  // Active campaigns — top-N rows with inline pause/resume buttons + type-summary chips
  const list = data.activeCampaigns || [];
  const cmpCard = el("div", { class: "card", style: "padding:12px;" }, [
    el(
      "div",
      { style: "display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;" },
      [
        el("div", { class: "wizard-section-title", style: "margin:0;" }, "Active campaigns"),
        el(
          "button",
          {
            type: "button",
            class: "btn btn-tiny btn-secondary",
            onclick: () => navigate("campaigns"),
          },
          "All →",
        ),
      ],
    ),
  ]);
  if (list.length === 0) {
    cmpCard.appendChild(
      el(
        "div",
        { class: "muted small", style: "padding:10px;text-align:center;" },
        "No active campaigns. Click 'All →' to start one.",
      ),
    );
  } else {
    for (const camp of list) {
      cmpCard.appendChild(renderInlineCampaignRow(camp));
    }
  }
  // Per-type summary chips at the bottom
  const summary = [
    ["Out", c.outreach?.active || 0],
    ["Email", c.email?.active || 0],
    ["DM", c.dm?.active || 0],
    ["Flows", c.workflows?.active || 0],
  ];
  cmpCard.appendChild(
    el(
      "div",
      {
        class: "muted small",
        style:
          "display:flex;gap:6px;margin-top:8px;padding-top:8px;border-top:1px solid var(--bg-3);",
      },
      summary.map(([k, n]) =>
        el(
          "span",
          {
            style: `padding:2px 6px;background:${n > 0 ? "var(--accent-soft)" : "var(--bg-3)"};border-radius:3px;font-size:10px;`,
          },
          `${k} ${n}`,
        ),
      ),
    ),
  );
  col.appendChild(cmpCard);

  return col;
}

// One campaign row with inline pause/resume button. Forces a re-poll on success.
function renderInlineCampaignRow(c) {
  const isActive = c.status === "active" || c.status === "running";
  const isPaused = c.status === "paused";
  const statusColor = isActive ? "var(--green)" : isPaused ? "var(--yellow)" : "var(--text-3)";
  const typeIcon =
    c.type === "email" ? "✉" : c.type === "dm" ? "✈" : c.type === "outreach" ? "📣" : "•";

  const actionBtn = isActive
    ? { op: "pause", label: "⏸", cls: "btn-secondary", title: "Pause campaign" }
    : isPaused
      ? { op: "resume", label: "▶", cls: "btn-primary", title: "Resume campaign" }
      : null;

  // Whole row drills into the campaign-detail visual breakdown.
  // The action button below stops propagation so pause/resume doesn't navigate.
  const drillTo = c.type && c.id ? `campaigns/${c.type}/${c.id}` : "campaigns";
  return el(
    "div",
    {
      style:
        "display:flex;align-items:center;gap:6px;padding:6px;background:var(--bg-2);border-radius:4px;margin-bottom:4px;border-left:2px solid " +
        statusColor +
        ";cursor:pointer;",
      title:
        c.type && c.id ? "Click to see what this campaign is doing" : "Click to view all campaigns",
      onclick: () => navigate(drillTo),
    },
    [
      el("span", { style: "font-size:12px;width:14px;text-align:center;flex-shrink:0;" }, typeIcon),
      el("div", { style: "flex:1;min-width:0;" }, [
        el(
          "div",
          {
            style:
              "font-size:11px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;",
            title: c.name,
          },
          c.name,
        ),
        el(
          "div",
          { class: "muted small mono", style: "font-size:9px;" },
          `${c.sent || 0} sent${c.failed ? ` · ${c.failed} failed` : ""}${c.replies ? ` · ${c.replies} replies` : ""}`,
        ),
      ]),
      actionBtn
        ? el(
            "button",
            {
              type: "button",
              class: `btn btn-tiny ${actionBtn.cls}`,
              style: "padding:1px 6px;font-size:10px;flex-shrink:0;",
              title: actionBtn.title,
              onclick: async (e) => {
                e.stopPropagation();
                e.currentTarget.disabled = true;
                e.currentTarget.textContent = "...";
                const r = await api("campaign-action", {
                  type: c.type,
                  id: c.id,
                  operation: actionBtn.op,
                });
                if (r?.error) toast(`${r.error}`, "err");
                else {
                  toast(`${actionBtn.label} ${c.name}`, "ok");
                  liveMapState.data = null;
                  renderLiveMap();
                }
              },
            },
            actionBtn.label,
          )
        : null,
    ],
  );
}

// Horizontal stacked bar with per-segment label and optional trend arrow
// 🔑 API key health card. One row per provider (CG/CMC/…); each row shows
// total throughput last minute + a strip of dots, one per key, color-coded
// by status (green=healthy, yellow=hot/saturated, red=cooled). Tooltip on
// each dot shows masked key + per-key counters.
//
// Pulls from data.apiKeys = { CG: { keyCount, perWindow, windowMs, keys: [...] }, ... }
// Empty object until a scraper has actually run since boot.
function renderApiKeyHealth(apiKeys) {
  const card = el("div", { class: "card", style: "padding:12px;" }, [
    el("div", { class: "wizard-section-title", style: "margin-bottom:10px;" }, "API key health"),
  ]);

  // Friendly names for the providers we currently know about.
  const PROVIDER_LABELS = {
    CG: { full: "CoinGecko", accent: "#7eb83a" },
    CMC: { full: "CoinMarketCap", accent: "#1d4ed8" },
  };

  for (const [name, info] of Object.entries(apiKeys)) {
    const label = PROVIDER_LABELS[name] || { full: name, accent: "var(--accent)" };
    const keys = Array.isArray(info.keys) ? info.keys : [];
    const perWindow = info.perWindow || 30;
    const totalCalls = keys.reduce((s, k) => s + (k.callsInWindow || 0), 0);
    const cap = info.keyCount * perWindow;
    const cooled = keys.filter((k) => (k.cooldownMs || 0) > 0).length;
    const inFlight = keys.reduce((s, k) => s + (k.inFlight || 0), 0);

    // Header row: provider · usage · cooled count.
    const header = el(
      "div",
      { style: "display:flex;align-items:center;gap:6px;margin-bottom:4px;font-size:11px;" },
      [
        el("span", { style: `width:6px;height:6px;border-radius:50%;background:${label.accent};` }),
        el("span", { style: "font-weight:600;flex:1;" }, label.full),
        el(
          "span",
          { class: "muted mono small" },
          `${totalCalls}/${cap}/min` +
            (inFlight > 0 ? ` · ${inFlight} in-flight` : "") +
            (cooled > 0 ? ` · ${cooled} cooled` : ""),
        ),
      ],
    );
    card.appendChild(header);

    // Per-key dot strip — one dot per key, colored by status.
    const strip = el("div", {
      style: "display:flex;gap:6px;margin:4px 0 10px;align-items:center;",
    });
    for (const k of keys) {
      const cooldownSec = Math.ceil((k.cooldownMs || 0) / 1000);
      const usagePct = Math.round((k.callsInWindow / perWindow) * 100);
      let dotColor;
      if (cooldownSec > 0) dotColor = "var(--red)";
      else if (usagePct >= 80) dotColor = "var(--yellow)";
      else if (usagePct > 0) dotColor = "var(--green)";
      else dotColor = "var(--text-4)";

      const tooltip =
        `${k.keyMasked}\n${k.callsInWindow}/${perWindow} calls in last minute` +
        (k.inFlight > 0 ? `\n${k.inFlight} in-flight` : "") +
        (cooldownSec > 0 ? `\nCOOLED — back online in ${cooldownSec}s` : "");

      strip.appendChild(
        el(
          "div",
          {
            style: `display:flex;flex-direction:column;align-items:center;gap:2px;`,
            title: tooltip,
          },
          [
            el("span", {
              style: `width:8px;height:8px;border-radius:50%;background:${dotColor};box-shadow:0 0 4px ${dotColor}40;`,
            }),
            el(
              "span",
              { class: "muted", style: "font-size:9px;font-family:var(--font-mono);" },
              String(k.callsInWindow || 0),
            ),
          ],
        ),
      );
    }
    // Fill remaining width with a spacer so the strip aligns left.
    strip.appendChild(el("span", { style: "flex:1;" }));
    card.appendChild(strip);
  }

  return card;
}

function queueBar(label, segments, trend, handlers = null) {
  const total = Math.max(
    segments.reduce((s, x) => s + x.value, 0),
    1,
  );
  const trendArrow =
    trend === null || trend === undefined
      ? null
      : trend > 0
        ? el("span", { style: "color:var(--red);" }, `▲ +${trend}`)
        : trend < 0
          ? el("span", { style: "color:var(--green);" }, `▼ ${trend}`)
          : el("span", { class: "muted" }, "─");

  const interactive = handlers && (handlers.onLabelClick || handlers.onSegmentClick);
  const labelEl = el(
    "span",
    {
      style: `font-weight:600;${handlers?.onLabelClick ? "cursor:pointer;" : ""}`,
      title: handlers?.onLabelClick ? `Click to view ${label.toLowerCase()} details` : "",
      onclick: handlers?.onLabelClick
        ? (e) => {
            e.stopPropagation();
            handlers.onLabelClick();
          }
        : undefined,
    },
    label,
  );

  const row = el(
    "div",
    {
      style: `margin-bottom:10px;${interactive ? "cursor:pointer;" : ""}`,
      onclick: handlers?.onLabelClick ? () => handlers.onLabelClick() : undefined,
    },
    [
      el(
        "div",
        {
          style:
            "display:flex;justify-content:space-between;align-items:baseline;font-size:11px;margin-bottom:3px;",
        },
        [
          labelEl,
          el("span", { class: "muted mono small" }, [
            ...segments
              .filter((s) => s.value > 0)
              .map((s) =>
                el(
                  "span",
                  {
                    style: `color:${s.color};margin-left:6px;${handlers?.onSegmentClick ? "cursor:pointer;text-decoration:underline dotted;text-underline-offset:2px;" : ""}`,
                    onclick: handlers?.onSegmentClick
                      ? (e) => {
                          e.stopPropagation();
                          handlers.onSegmentClick(s.label);
                        }
                      : undefined,
                    title: handlers?.onSegmentClick
                      ? `View ${s.label} ${label.toLowerCase()} tasks`
                      : "",
                  },
                  `${s.label} ${s.value}`,
                ),
              ),
            trendArrow ? el("span", { style: "margin-left:8px;" }, [trendArrow]) : null,
          ]),
        ],
      ),
      el(
        "div",
        {
          style:
            "height:8px;background:var(--bg-3);border-radius:4px;overflow:hidden;display:flex;",
        },
        segments
          .filter((s) => s.value > 0)
          .map((s) =>
            el("div", {
              style: `height:100%;background:${s.color};width:${(s.value / total) * 100}%;${handlers?.onSegmentClick ? "cursor:pointer;" : ""}`,
              title: `${s.label}: ${s.value}${handlers?.onSegmentClick ? " — click to view" : ""}`,
              onclick: handlers?.onSegmentClick
                ? (e) => {
                    e.stopPropagation();
                    handlers.onSegmentClick(s.label);
                  }
                : undefined,
            }),
          ),
      ),
    ],
  );
  return row;
}
