// dashboard-live-now-drawer-per-item-progres.js — extracted verbatim from dashboard.js (pure move).

// ── Live-now drawer: per-item progress for currently-running automations ─
//
// Opened by clicking the green "N running" pill in the cockpit's status
// strip. Shows one card per running item (custom workflow, campaign
// loop, email loop, listener, forwarder, auto-responder) with the
// richest progress data we already have on hand:
//   - runtime ("running for 12m")
//   - schedule + last run status (for customs)
//   - pause / cancel buttons (for loops)
//   - "View details →" link to the full per-type detail page
//
// Auto-refreshes every 5s while open so progress stays live without
// requiring a manual refresh. Stops refreshing on drawer close.
//
// Future extension (V2): per-item bespoke stats (campaign sent/replied
// counts pulled from outreach_events, email opens from
// email_tracking_events, items_kept/processed for customs). Stubbed
// today via the "View details" link to existing detail pages.

let _liveNowDrawerTimer = null;

function openLiveNowDrawer(opsLive) {
  const body = renderLiveNowDrawerBody(opsLive);
  // Phase C2: count includes running compositions
  const totalRunning =
    (opsLive?.customWorkflows?.length || 0) +
    (opsLive?.longRunningLoops?.length || 0) +
    (opsLive?.compositionRuns || []).filter((r) => r.status === "running").length;
  openDrawer(`Live now — ${totalRunning} running`, body);
  logTelemetry("automations", "live_drawer_open", { total: totalRunning });

  // Auto-refresh loop. Stops when the drawer is closed (visibility check).
  if (_liveNowDrawerTimer) clearInterval(_liveNowDrawerTimer);
  _liveNowDrawerTimer = setInterval(async () => {
    const drawer = document.getElementById("drawer");
    if (!drawer || !drawer.classList.contains("show")) {
      clearInterval(_liveNowDrawerTimer);
      _liveNowDrawerTimer = null;
      return;
    }
    try {
      const fresh = await api("ops-live").catch(() => null);
      if (!fresh) return;
      const newBody = renderLiveNowDrawerBody(fresh);
      const drawerBody = document.getElementById("drawer-body");
      if (drawerBody) {
        drawerBody.innerHTML = "";
        drawerBody.appendChild(newBody);
      }
      const newTotal =
        (fresh.customWorkflows?.length || 0) +
        (fresh.longRunningLoops?.length || 0) +
        (fresh.compositionRuns || []).filter((r) => r.status === "running").length;
      const titleEl = document.getElementById("drawer-title");
      if (titleEl) titleEl.textContent = `Live now — ${newTotal} running`;
    } catch (err) {
      console.warn("[live-now drawer] refresh failed:", err);
    }
  }, 5000);
}

// Compose the drawer body. Pure render — no fetching here, the caller
// (openLiveNowDrawer + the auto-refresh interval) supplies fresh data.
function renderLiveNowDrawerBody(opsLive) {
  const customs = opsLive?.customWorkflows || [];
  const loops = opsLive?.longRunningLoops || [];
  // Phase C2 — composition runs (running + recently finished within 30 min)
  const compRuns = opsLive?.compositionRuns || [];
  const compRunning = compRuns.filter((r) => r.status === "running");
  const compRecent = compRuns.filter((r) => r.status !== "running");

  const wrap = el("div", { style: "display:flex;flex-direction:column;gap:14px;" });

  // Auto-refresh hint at the top so the user knows numbers are live.
  wrap.appendChild(
    el(
      "div",
      {
        style: [
          "display:flex",
          "align-items:center",
          "gap:8px",
          "padding:8px 12px",
          "background:rgba(34,197,94,0.06)",
          "border:1px solid rgba(34,197,94,0.18)",
          "border-radius:8px",
          "font-size:11px",
          "color:#86efac",
        ].join(";"),
      },
      [
        el("span", {
          style:
            "display:inline-block;width:6px;height:6px;border-radius:50%;background:#22c55e;animation:status-pulse 2s ease-out infinite;",
        }),
        el("span", {}, "Live — refreshing every 5 seconds"),
      ],
    ),
  );

  if (customs.length === 0 && loops.length === 0 && compRuns.length === 0) {
    wrap.appendChild(
      el(
        "div",
        {
          style: "padding:14px;color:#9ca3af;font-size:12px;text-align:center;",
        },
        "Nothing is running right now.",
      ),
    );
    return wrap;
  }

  // ── Composer compositions section (Phase C2) ────────────────────
  if (compRunning.length > 0) {
    wrap.appendChild(
      el(
        "div",
        {
          style:
            "font-size:11px;color:#9ca3af;text-transform:uppercase;letter-spacing:0.05em;font-weight:600;margin-top:4px;",
        },
        `🧩 Composer running (${compRunning.length})`,
      ),
    );
    for (const r of compRunning) wrap.appendChild(renderCompositionLiveCard(r, true));
  }
  if (compRecent.length > 0) {
    wrap.appendChild(
      el(
        "div",
        {
          style:
            "font-size:11px;color:#9ca3af;text-transform:uppercase;letter-spacing:0.05em;font-weight:600;margin-top:8px;",
        },
        `🧩 Composer recent (${compRecent.length}) — last 30 min`,
      ),
    );
    for (const r of compRecent) wrap.appendChild(renderCompositionLiveCard(r, false));
  }

  // ── Custom workflows section ──────────────────────────────────────
  if (customs.length > 0) {
    wrap.appendChild(
      el(
        "div",
        {
          style:
            "font-size:11px;color:#9ca3af;text-transform:uppercase;letter-spacing:0.05em;font-weight:600;margin-top:8px;",
        },
        `Custom workflows (${customs.length})`,
      ),
    );
    for (const c of customs) wrap.appendChild(renderCustomLiveCard(c));
  }

  // ── Long-running loops section ────────────────────────────────────
  if (loops.length > 0) {
    wrap.appendChild(
      el(
        "div",
        {
          style:
            "font-size:11px;color:#9ca3af;text-transform:uppercase;letter-spacing:0.05em;font-weight:600;margin-top:8px;",
        },
        `Active loops (${loops.length})`,
      ),
    );
    for (const l of loops) wrap.appendChild(renderLoopLiveCard(l));
  }

  return wrap;
}

// Phase C2 — composition run live card. Mirrors the visual rhythm of the
// custom-workflow card but routes click → workflows/canvas (the n8n editor)
// and surfaces composition-specific fields (audience size, plays exec).
function renderCompositionLiveCard(r, isRunning) {
  const statusColors = {
    running: "#3b82f6",
    success: "#10b981",
    error: "#ef4444",
    partial: "#daaa5a",
    skipped: "#94a3b8",
  };
  const statusColor = statusColors[r.status] || "#5adada";
  const accent = isRunning ? "#5adada" : statusColor;
  const prog = r.progress || {};

  const stat = (label, value, color = "#e5e7eb") =>
    el(
      "div",
      {
        style: "display:flex;flex-direction:column;gap:1px;min-width:60px;",
      },
      [
        el(
          "div",
          {
            style:
              "font-size:10px;color:#6b7280;text-transform:uppercase;letter-spacing:0.04em;font-weight:600;",
          },
          label,
        ),
        el(
          "div",
          {
            style: `font-size:14px;font-weight:600;color:${color};font-variant-numeric:tabular-nums;`,
          },
          String(value),
        ),
      ],
    );

  return el(
    "div",
    {
      style: [
        "background:#161618",
        "border:1px solid #26262a",
        `border-left:3px solid ${accent}`,
        "border-radius:8px",
        "padding:12px 14px",
        "display:flex",
        "flex-direction:column",
        "gap:10px",
        "cursor:pointer",
      ].join(";"),
      onclick: () => {
        navigate(`workflows/canvas?id=${r.compositionId}`);
      },
      title: "Open in canvas editor",
    },
    [
      el("div", { style: "display:flex;align-items:center;gap:10px;" }, [
        isRunning
          ? el("span", {
              style: `display:inline-block;width:8px;height:8px;border-radius:50%;background:${accent};animation:status-pulse 2s ease-out infinite;flex-shrink:0;`,
            })
          : el("span", {
              style: `display:inline-block;width:8px;height:8px;border-radius:50%;background:${accent};flex-shrink:0;`,
            }),
        el("div", { style: "flex:1;min-width:0;" }, [
          el(
            "div",
            {
              style:
                "font-size:13px;font-weight:600;color:#e5e7eb;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;",
            },
            [el("span", { style: "color:#5adada;margin-right:6px;font-size:10px;" }, "🧩"), r.name],
          ),
          el(
            "div",
            {
              style:
                "font-size:11px;color:#9ca3af;font-family:ui-monospace,monospace;margin-top:2px;",
            },
            `${r.triggeredBy || "manual"} · run #${r.id} · ${isRunning ? "started" : "finished"} ${_liveFmtSince(isRunning ? r.startedAt : r.finishedAt || r.startedAt)} ago`,
          ),
        ]),
        el(
          "span",
          {
            style: `font-size:10px;font-family:ui-monospace,monospace;letter-spacing:0.04em;color:${statusColor};background:${statusColor}22;border:1px solid ${statusColor}55;padding:2px 7px;border-radius:10px;flex-shrink:0;`,
          },
          r.status.toUpperCase(),
        ),
      ]),
      prog.audienceSize > 0 || prog.playsExecuted > 0
        ? el(
            "div",
            {
              style: [
                "display:flex",
                "gap:18px",
                "padding:8px 12px",
                "background:rgba(90,218,218,0.04)",
                "border:1px solid rgba(90,218,218,0.18)",
                "border-radius:6px",
              ].join(";"),
            },
            [
              stat("Audience", prog.audienceSize, "#a7e8e8"),
              stat("Plays", prog.playsExecuted, "#a7e8e8"),
              stat("OK", prog.playsSucceeded, "#86efac"),
              prog.playsFailed > 0 ? stat("Fail", prog.playsFailed, "#fca5a5") : null,
            ].filter(Boolean),
          )
        : null,
      prog.error
        ? el(
            "div",
            {
              style: [
                "padding:6px 10px",
                "background:rgba(239,68,68,0.06)",
                "border:1px solid rgba(239,68,68,0.25)",
                "border-radius:5px",
                "font-size:11px",
                "color:#fca5a5",
                "font-family:ui-monospace,monospace",
                "white-space:nowrap",
                "overflow:hidden",
                "text-overflow:ellipsis",
              ].join(";"),
              title: prog.error,
            },
            [el("span", { style: "margin-right:6px;" }, "⚠"), el("span", {}, prog.error)],
          )
        : null,
    ].filter(Boolean),
  );
}

// Helper for "X minutes ago" style relative time.
function _liveFmtSince(ts) {
  if (!ts) return "—";
  const ms = Date.now() - new Date(ts).getTime();
  const sec = Math.max(0, Math.round(ms / 1000));
  if (sec < 60) return `${sec}s`;
  if (sec < 3600) return `${Math.round(sec / 60)}m`;
  const h = Math.floor(sec / 3600);
  const m = Math.round((sec % 3600) / 60);
  return m > 0 ? `${h}h ${m}m` : `${h}h`;
}

function renderCustomLiveCard(c) {
  const lastStatus = c.lastStatus || "—";
  const statusPalette = {
    success: "#10b981",
    error: "#ef4444",
    skipped: "#94a3b8",
    running: "#3b82f6",
  };
  const lastColor = statusPalette[lastStatus] || "#94a3b8";
  const prog = c.progress || {};

  // Inline stat cell — keeps the visual rhythm consistent across all
  // metric pairs in the drawer.
  const stat = (label, value, color = "#e5e7eb") =>
    el(
      "div",
      {
        style: "display:flex;flex-direction:column;gap:1px;min-width:60px;",
      },
      [
        el(
          "div",
          {
            style:
              "font-size:10px;color:#6b7280;text-transform:uppercase;letter-spacing:0.04em;font-weight:600;",
          },
          label,
        ),
        el(
          "div",
          {
            style: `font-size:14px;font-weight:600;color:${color};font-variant-numeric:tabular-nums;`,
          },
          String(value),
        ),
      ],
    );

  return el(
    "div",
    {
      style: [
        "background:#161618",
        "border:1px solid #26262a",
        "border-left:3px solid #22c55e",
        "border-radius:8px",
        "padding:12px 14px",
        "display:flex",
        "flex-direction:column",
        "gap:10px",
      ].join(";"),
    },
    [
      // Title row
      el("div", { style: "display:flex;align-items:center;gap:10px;" }, [
        el("span", {
          style:
            "display:inline-block;width:8px;height:8px;border-radius:50%;background:#22c55e;animation:status-pulse 2s ease-out infinite;flex-shrink:0;",
        }),
        el("div", { style: "flex:1;min-width:0;" }, [
          el(
            "div",
            {
              style:
                "font-size:13px;font-weight:600;color:#e5e7eb;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;",
            },
            c.name,
          ),
          el(
            "div",
            {
              style:
                "font-size:11px;color:#9ca3af;font-family:ui-monospace,monospace;margin-top:2px;",
            },
            `${c.sourcePresetId || "—"} · ${c.schedule || "—"} · last run ${c.lastRunAt ? _liveFmtSince(c.lastRunAt) + " ago" : "never"}`,
          ),
        ]),
      ]),
      // Inline metrics — pulled from latest run. Hidden when 0/0.
      prog.itemsProcessed > 0 || prog.itemsKept > 0
        ? el(
            "div",
            {
              style: [
                "display:flex",
                "gap:18px",
                "padding:8px 12px",
                "background:rgba(34,197,94,0.04)",
                "border:1px solid rgba(34,197,94,0.18)",
                "border-radius:6px",
              ].join(";"),
            },
            [
              stat("Processed", prog.itemsProcessed, "#86efac"),
              stat("Kept", prog.itemsKept, "#86efac"),
              stat("Status", lastStatus, lastColor),
            ],
          )
        : null,
      // Error preview if the latest run failed.
      prog.error
        ? el(
            "div",
            {
              style: [
                "padding:6px 10px",
                "background:rgba(239,68,68,0.06)",
                "border:1px solid rgba(239,68,68,0.25)",
                "border-radius:5px",
                "font-size:11px",
                "color:#fca5a5",
                "font-family:ui-monospace,monospace",
                "white-space:nowrap",
                "overflow:hidden",
                "text-overflow:ellipsis",
              ].join(";"),
              title: prog.error,
            },
            [el("span", { style: "margin-right:6px;" }, "⚠"), el("span", {}, prog.error)],
          )
        : null,
      // Action row — view details
      el("div", { style: "display:flex;gap:6px;margin-top:auto;" }, [
        el(
          "button",
          {
            type: "button",
            style:
              "padding:5px 10px;background:rgba(99,102,241,0.12);border:1px solid rgba(99,102,241,0.35);border-radius:5px;color:#a5b4fc;font-size:11px;cursor:pointer;font-weight:500;",
            title: "Open the workflow's full detail page",
            onclick: () => {
              closeDrawer();
              if (_liveNowDrawerTimer) {
                clearInterval(_liveNowDrawerTimer);
                _liveNowDrawerTimer = null;
              }
              // ops-live returns the raw numeric DB id for custom workflows;
              // the viewer routes by a `custom_` prefix (else it hits the
              // preset endpoint and 404s with "Workflow '<id>' not found").
              navigate(`automations/view/custom_${c.id}`);
            },
          },
          "View details + recent runs →",
        ),
      ]),
    ],
  );
}

function renderLoopLiveCard(l) {
  const typeLabel =
    {
      campaign: "Telegram campaign",
      email_campaign: "Email campaign",
      active_member: "Group listener",
      auto_responder: "Auto-reply",
      forwarder: "Forwarder",
    }[l.type] || l.type;

  const detailRoute = {
    campaign: `campaigns/dm/${l.id}`,
    email_campaign: `campaigns/email/${l.id}`,
    active_member: `telegram/activemember`,
    auto_responder: `telegram/autoreply`,
    forwarder: `telegram/forward`,
  }[l.type];

  // Pause + cancel handlers — close drawer + re-render the page so
  // the row leaves Live-now without the user having to manually refresh.
  const pauseBtn = el(
    "button",
    {
      type: "button",
      style:
        "padding:5px 10px;background:rgba(234,179,8,0.15);border:1px solid rgba(234,179,8,0.4);border-radius:5px;color:#fde68a;font-size:11px;cursor:pointer;font-weight:500;",
      title: "Pause this loop (keep settings, can be resumed)",
      onclick: async (ev) => {
        ev.stopPropagation();
        const r = await api("ops-loop-action", { type: l.type, id: l.id, action: "pause" });
        if (r?.error) {
          toast(r.error, "err");
          return;
        }
        toast(`Paused ${typeLabel}`, "ok");
        closeDrawer();
        if (_liveNowDrawerTimer) {
          clearInterval(_liveNowDrawerTimer);
          _liveNowDrawerTimer = null;
        }
        renderAutomations();
      },
    },
    "⏸ Pause",
  );

  const cancelBtn = el(
    "button",
    {
      type: "button",
      style:
        "padding:5px 10px;background:rgba(239,68,68,0.12);border:1px solid rgba(239,68,68,0.35);border-radius:5px;color:#fca5a5;font-size:11px;cursor:pointer;font-weight:500;",
      title: "Cancel — destructive, won't auto-resume",
      onclick: async (ev) => {
        ev.stopPropagation();
        if (
          !confirm(
            `Cancel ${typeLabel} "${l.name}"?\n\nThis stops the loop. Re-start from its detail page if you want it back.`,
          )
        )
          return;
        const r = await api("ops-loop-action", { type: l.type, id: l.id, action: "cancel" });
        if (r?.error) {
          toast(r.error, "err");
          return;
        }
        toast(`Cancelled ${typeLabel}`, "ok");
        closeDrawer();
        if (_liveNowDrawerTimer) {
          clearInterval(_liveNowDrawerTimer);
          _liveNowDrawerTimer = null;
        }
        renderAutomations();
      },
    },
    "✕ Cancel",
  );

  const detailsBtn = detailRoute
    ? el(
        "button",
        {
          type: "button",
          style:
            "padding:5px 10px;background:rgba(99,102,241,0.12);border:1px solid rgba(99,102,241,0.35);border-radius:5px;color:#a5b4fc;font-size:11px;cursor:pointer;font-weight:500;",
          title: `Open ${typeLabel} details — full progress, recent activity, results`,
          onclick: () => {
            closeDrawer();
            if (_liveNowDrawerTimer) {
              clearInterval(_liveNowDrawerTimer);
              _liveNowDrawerTimer = null;
            }
            navigate(detailRoute);
          },
        },
        "View progress + results →",
      )
    : null;

  // Inline progress block — populated for campaigns + email_campaigns.
  // Other loop types (active_member, auto_responder, forwarder) don't
  // have campaign-level counters; their detail pages are the source of
  // truth.
  const prog = l.progress || {};
  const stat = (label, value, color = "#e5e7eb", sub = "") =>
    el(
      "div",
      {
        style: "display:flex;flex-direction:column;gap:1px;min-width:60px;",
      },
      [
        el(
          "div",
          {
            style:
              "font-size:10px;color:#6b7280;text-transform:uppercase;letter-spacing:0.04em;font-weight:600;",
          },
          label,
        ),
        el(
          "div",
          {
            style: `font-size:14px;font-weight:600;color:${color};font-variant-numeric:tabular-nums;`,
          },
          String(value),
        ),
        sub
          ? el(
              "div",
              { style: "font-size:10px;color:#71717a;font-family:ui-monospace,monospace;" },
              sub,
            )
          : null,
      ],
    );

  let progressBlock = null;
  if (l.type === "campaign" && (prog.totalTargets > 0 || prog.sent > 0)) {
    const pctSent =
      prog.totalTargets > 0 ? Math.min(100, Math.round((prog.sent / prog.totalTargets) * 100)) : 0;
    const pctReplied = prog.sent > 0 ? Math.round((prog.replied / prog.sent) * 100) : 0;
    progressBlock = el("div", {}, [
      // Numeric stats grid
      el(
        "div",
        {
          style: [
            "display:flex",
            "gap:18px",
            "flex-wrap:wrap",
            "padding:8px 12px",
            "background:rgba(59,130,246,0.04)",
            "border:1px solid rgba(59,130,246,0.18)",
            "border-radius:6px",
          ].join(";"),
        },
        [
          stat(
            "Sent",
            prog.totalTargets > 0 ? `${prog.sent} / ${prog.totalTargets}` : prog.sent,
            "#93c5fd",
          ),
          stat(
            "Replied",
            prog.replied,
            prog.replied > 0 ? "#86efac" : "#9ca3af",
            prog.sent > 0 ? `${pctReplied}% rate` : "",
          ),
          stat("Failed", prog.failed, prog.failed > 0 ? "#fca5a5" : "#71717a"),
        ],
      ),
      // Progress bar — only when totalTargets known
      prog.totalTargets > 0
        ? el(
            "div",
            {
              style: [
                "height:4px",
                "border-radius:2px",
                "overflow:hidden",
                "background:rgba(255,255,255,0.06)",
                "margin-top:6px",
              ].join(";"),
            },
            [
              el("div", {
                style: [
                  `width:${pctSent}%`,
                  "height:100%",
                  "background:linear-gradient(90deg,#3b82f6,#22c55e)",
                  "transition:width 600ms ease-out",
                ].join(";"),
                title: `${pctSent}% sent`,
              }),
            ],
          )
        : null,
    ]);
  } else if (l.type === "email_campaign" && (prog.totalTargets > 0 || prog.sent > 0)) {
    const pctSent =
      prog.totalTargets > 0 ? Math.min(100, Math.round((prog.sent / prog.totalTargets) * 100)) : 0;
    const pctOpened = prog.sent > 0 ? Math.round((prog.opened / prog.sent) * 100) : 0;
    progressBlock = el("div", {}, [
      el(
        "div",
        {
          style: [
            "display:flex",
            "gap:18px",
            "flex-wrap:wrap",
            "padding:8px 12px",
            "background:rgba(59,130,246,0.04)",
            "border:1px solid rgba(59,130,246,0.18)",
            "border-radius:6px",
          ].join(";"),
        },
        [
          stat(
            "Sent",
            prog.totalTargets > 0 ? `${prog.sent} / ${prog.totalTargets}` : prog.sent,
            "#93c5fd",
          ),
          stat(
            "Opened",
            prog.opened,
            prog.opened > 0 ? "#86efac" : "#9ca3af",
            prog.sent > 0 ? `${pctOpened}% rate` : "",
          ),
          stat("Bounced", prog.bounced, prog.bounced > 0 ? "#fca5a5" : "#71717a"),
          prog.unsubscribed > 0 ? stat("Unsubs", prog.unsubscribed, "#fde68a") : null,
        ].filter(Boolean),
      ),
      prog.totalTargets > 0
        ? el(
            "div",
            {
              style: [
                "height:4px",
                "border-radius:2px",
                "overflow:hidden",
                "background:rgba(255,255,255,0.06)",
                "margin-top:6px",
              ].join(";"),
            },
            [
              el("div", {
                style: [
                  `width:${pctSent}%`,
                  "height:100%",
                  "background:linear-gradient(90deg,#3b82f6,#22c55e)",
                  "transition:width 600ms ease-out",
                ].join(";"),
                title: `${pctSent}% sent`,
              }),
            ],
          )
        : null,
    ]);
  }

  return el(
    "div",
    {
      style: [
        "background:#161618",
        "border:1px solid #26262a",
        "border-left:3px solid #3b82f6",
        "border-radius:8px",
        "padding:12px 14px",
        "display:flex",
        "flex-direction:column",
        "gap:10px",
      ].join(";"),
    },
    [
      el("div", { style: "display:flex;align-items:center;gap:10px;" }, [
        el("span", {
          style:
            "display:inline-block;width:8px;height:8px;border-radius:50%;background:#3b82f6;animation:status-pulse 2s ease-out infinite;flex-shrink:0;",
        }),
        el("div", { style: "flex:1;min-width:0;" }, [
          el(
            "div",
            {
              style:
                "font-size:13px;font-weight:600;color:#e5e7eb;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;",
            },
            l.name,
          ),
          el(
            "div",
            {
              style:
                "font-size:11px;color:#9ca3af;font-family:ui-monospace,monospace;margin-top:2px;",
            },
            `${typeLabel} · running for ${_liveFmtSince(l.since)}`,
          ),
        ]),
      ]),
      progressBlock,
      el(
        "div",
        { style: "display:flex;gap:6px;flex-wrap:wrap;margin-top:auto;" },
        [detailsBtn, pauseBtn, cancelBtn].filter(Boolean),
      ),
    ],
  );
}
