// dashboard-health-safety-dashboard.js — extracted verbatim from dashboard.js (pure move).

// ─── Health & Safety dashboard ───────────────────────────────────
// Per-platform account health + DNC suggestions (inbox replies that
// look like opt-outs) + DNC registry. Single source of truth for "are
// any of my accounts in danger?" and "have I respected opt-outs?".

let healthTab = "accounts";

async function renderHealth() {
  showLoading("Loading health snapshot…");

  const tabs = el("div", { class: "tabs" }, [
    tabBtn("accounts", "Accounts", () => {
      healthTab = "accounts";
      renderHealth();
    }),
    tabBtn("suggestions", "DNC suggestions", () => {
      healthTab = "suggestions";
      renderHealth();
    }),
    tabBtn("dnc", "Do-not-contact", () => {
      healthTab = "dnc";
      renderHealth();
    }),
  ]);
  setTimeout(() => {
    $$(".tab").forEach((t) =>
      t.classList.toggle("active", t.getAttribute("data-tab") === healthTab),
    );
  }, 0);

  const header = el("div", { class: "page-header" }, [
    el("div", {}, [
      el("div", { class: "page-title" }, "Health & Safety"),
      el("div", { class: "page-subtitle" }, "Account health across platforms · opt-out registry"),
    ]),
    el(
      "button",
      { class: "btn btn-secondary btn-tiny", type: "button", onclick: renderHealth },
      "↻ Refresh",
    ),
  ]);

  setContentNode(el("div", {}, [header, tabs, el("div", { id: "health-body" })]));

  const slot = $("#health-body");
  if (!slot) return;

  if (healthTab === "accounts") slot.appendChild(await renderHealthAccounts());
  else if (healthTab === "suggestions") slot.appendChild(await renderDncSuggestions());
  else slot.appendChild(await renderDncList());
}

async function renderHealthAccounts() {
  const data = await api("health-accounts").catch((err) => ({ error: err.message }));
  if (data?.error) return el("div", { class: "muted" }, `Error: ${data.error}`);

  const summary = data.summary || { totalAccounts: 0, atRisk: 0, avgHealth: null };
  const platforms = data.platforms || {};

  const wrap = el("div", {});

  // Top stats
  wrap.appendChild(
    el("div", { class: "card" }, [
      el("div", { class: "stats-grid" }, [
        statCard("Connected", summary.totalAccounts, "across all platforms"),
        statCard(
          "At risk",
          summary.atRisk,
          summary.atRisk > 0 ? "needs attention" : "all healthy",
          summary.atRisk > 0 ? "warning" : null,
        ),
        statCard("Avg health", summary.avgHealth != null ? `${summary.avgHealth}%` : "—", ""),
      ]),
    ]),
  );

  // Per-platform sections
  const PLATFORM_LABELS = {
    twitter: "X / Twitter",
    linkedin: "LinkedIn",
    telegram: "Telegram",
    email: "Email",
  };
  const PLATFORM_EMOJI = { twitter: "🐦", linkedin: "💼", telegram: "💬", email: "✉️" };

  for (const platform of ["twitter", "linkedin", "telegram", "email"]) {
    const accounts = platforms[platform] || [];
    if (accounts.length === 0) continue;
    wrap.appendChild(
      el("div", { class: "card" }, [
        el(
          "div",
          { class: "card-title" },
          `${PLATFORM_EMOJI[platform] || "•"} ${PLATFORM_LABELS[platform] || platform} (${accounts.length})`,
        ),
        ...accounts.map(renderAccountHealthRow),
      ]),
    );
  }

  if (summary.totalAccounts === 0) {
    wrap.appendChild(
      el("div", { class: "empty-state", style: "padding: 32px;" }, [
        el("div", { class: "empty-state-icon" }, "👤"),
        el("div", { class: "empty-state-title" }, "No accounts connected"),
        el(
          "div",
          { class: "empty-state-hint" },
          "Connect at least one account to see health stats.",
        ),
      ]),
    );
  }

  return wrap;
}

function renderAccountHealthRow(a) {
  const healthScore = a.healthScore ?? 0;
  const healthClass = healthScore >= 70 ? "healthy" : healthScore >= 40 ? "degraded" : "low";
  const usagePct =
    a.todayActions != null && a.dailyLimit
      ? Math.round((a.todayActions / a.dailyLimit) * 100)
      : null;

  const statusBadge =
    {
      active: el("span", { class: "badge badge-green" }, "active"),
      rate_limited: el("span", { class: "badge badge-yellow" }, "rate-limited"),
      logged_out: el("span", { class: "badge badge-gray" }, "logged out"),
      expired: el("span", { class: "badge badge-gray" }, "expired"),
      banned: el("span", { class: "badge badge-red" }, "banned"),
    }[a.status] || el("span", { class: "badge badge-gray" }, a.status || "unknown");

  return el(
    "div",
    {
      class: "channel-row",
      style: `padding: 12px; border-bottom: 1px solid var(--border); ${a.atRisk ? "background: rgba(251, 191, 36, 0.05);" : ""}`,
    },
    [
      el("div", { style: "flex: 1; min-width: 0;" }, [
        el("div", { style: "display: flex; align-items: center; gap: 8px; flex-wrap: wrap;" }, [
          el("span", { class: "primary-cell" }, a.identifier),
          statusBadge,
          a.atRisk ? el("span", { class: "badge badge-red" }, "⚠ at risk") : null,
          a.warmupDay != null
            ? el("span", { class: "muted small" }, `warmup d${a.warmupDay}`)
            : null,
          a.cooldownUntil
            ? el("span", { class: "muted small" }, `cooldown until ${fmtDate(a.cooldownUntil)}`)
            : null,
        ]),
        // Health bar
        el("div", { style: "display: flex; align-items: center; gap: 8px; margin-top: 8px;" }, [
          el("div", { class: "channel-bar", style: "flex: 1; max-width: 200px;" }, [
            el("div", {
              class: `channel-bar-fill ${healthClass}`,
              style: `width: ${healthScore}%`,
            }),
          ]),
          el("span", { class: "muted mono small" }, `${healthScore}% health`),
          a.todayActions != null
            ? el(
                "span",
                { class: "muted small" },
                [
                  `· ${a.todayActions}`,
                  a.dailyLimit ? `/${a.dailyLimit}` : "",
                  " today",
                  usagePct != null && usagePct >= 80 ? ` (${usagePct}%)` : "",
                ].join(""),
              )
            : null,
          a.todayFailures > 0
            ? el(
                "span",
                { class: "muted small", style: "color: var(--red);" },
                `· ${a.todayFailures} failed`,
              )
            : null,
        ]),
        // Recent failures (collapsed if many)
        a.recentFailures && a.recentFailures.length > 0
          ? el(
              "div",
              {
                class: "muted small",
                style:
                  "margin-top: 6px; padding: 6px 8px; background: var(--bg-1); border-radius: var(--radius-sm); border-left: 2px solid var(--red);",
              },
              [
                el(
                  "div",
                  { style: "font-weight: 600; margin-bottom: 4px;" },
                  `Last ${a.recentFailures.length} failures:`,
                ),
                ...a.recentFailures
                  .slice(0, 3)
                  .map((f) =>
                    el(
                      "div",
                      { style: "font-family: var(--font-mono); font-size: 10px;" },
                      `${f.type}: ${f.error || "no error message"}`,
                    ),
                  ),
              ],
            )
          : null,
      ]),
    ],
  );
}

async function renderDncSuggestions() {
  const data = await api("dnc-suggestions").catch((err) => ({ error: err.message }));
  if (data?.error) return el("div", { class: "muted" }, `Error: ${data.error}`);
  const suggestions = data.suggestions || [];

  if (suggestions.length === 0) {
    return el("div", { class: "empty-state", style: "padding: 32px;" }, [
      el("div", { class: "empty-state-icon" }, "✓"),
      el("div", { class: "empty-state-title" }, "No opt-out signals detected"),
      el(
        "div",
        { class: "empty-state-hint" },
        "We scan recent inbox replies for phrases like 'unsubscribe', 'remove me', 'stop emailing'. Nothing matched in the last 60 days.",
      ),
    ]);
  }

  // Selection state lives outside the render function so the user keeps
  // their picks if they accidentally tap-and-hold somewhere mid-action.
  const selected = new Set();

  // Bulk action bar — updates as the user (de)selects.
  const selectedCount = el("span", { class: "muted small" }, "0 selected");
  const flagAllBtn = el(
    "button",
    {
      class: "btn btn-tiny btn-danger",
      type: "button",
      disabled: "disabled",
      onclick: async (ev) => {
        const ids = [...selected];
        if (ids.length === 0) return;
        if (
          !confirm(
            `Mark ${ids.length} contact${ids.length === 1 ? "" : "s"} as do-not-contact? They'll be skipped on every outreach cycle.`,
          )
        )
          return;
        await withProgress(ev.currentTarget, async () => {
          let ok = 0,
            failed = 0;
          for (const id of ids) {
            const s = suggestions.find((x) => x.contactId === id);
            const reason = s ? `opt-out reply: "${s.matchedPhrase}"` : "bulk opt-out flag";
            const r = await api("contact-dnc-toggle", {
              contactId: id,
              body: { on: true, reason },
            });
            if (r?.error) failed++;
            else ok++;
          }
          toast(`✓ Flagged ${ok}${failed ? `, ${failed} failed` : ""}`, failed ? "err" : "ok");
          renderHealth();
        });
      },
    },
    "🚫 Flag selected",
  );

  const skipAllBtn = el(
    "button",
    {
      class: "btn btn-tiny btn-secondary",
      type: "button",
      disabled: "disabled",
      title: "Hide these from the suggestions list (keeps the contacts active)",
      onclick: (ev) => {
        ev.stopPropagation();
        // Soft-skip: just hide the cards locally. Server-side false positives
        // can be addressed by inserting a 'reply_sent' style marker, but for
        // MVP we just clear the selection.
        for (const id of selected) {
          const card = document.querySelector(`[data-suggestion-id="${id}"]`);
          if (card) card.style.display = "none";
        }
        selected.clear();
        updateBulkBar();
        toast(`Hidden ${selected.size || ""} from view`, "info");
      },
    },
    "Skip selected",
  );

  function updateBulkBar() {
    const n = selected.size;
    selectedCount.textContent = `${n} selected`;
    if (n > 0) {
      flagAllBtn.removeAttribute("disabled");
      skipAllBtn.removeAttribute("disabled");
    } else {
      flagAllBtn.setAttribute("disabled", "disabled");
      skipAllBtn.setAttribute("disabled", "disabled");
    }
  }

  // Card builder — checkbox in the top-left, click anywhere else opens
  // the contact drawer.
  function suggestionCard(s) {
    const checkbox = el("input", {
      type: "checkbox",
      style: "margin: 4px 8px 0 0; flex-shrink: 0;",
      onchange: (e) => {
        e.stopPropagation();
        if (e.target.checked) selected.add(s.contactId);
        else selected.delete(s.contactId);
        updateBulkBar();
      },
    });

    return el(
      "div",
      {
        class: "card",
        "data-suggestion-id": String(s.contactId),
        style: "padding: 12px; margin-bottom: 8px; display: flex; gap: 4px;",
      },
      [
        checkbox,
        el("div", { style: "flex: 1; min-width: 0;" }, [
          el(
            "div",
            {
              style:
                "display: flex; align-items: center; gap: 8px; margin-bottom: 6px; flex-wrap: wrap;",
            },
            [
              el(
                "span",
                {
                  class: "primary-cell",
                  style: "cursor: pointer;",
                  onclick: () => showContactDrawer(s.contactId),
                },
                s.displayName,
              ),
              el("span", { class: "badge badge-yellow" }, `matched: "${s.matchedPhrase}"`),
              s.platform ? el("span", { class: "muted small" }, `· ${s.platform}`) : null,
              el("span", { class: "muted small", style: "margin-left: auto;" }, fmtDate(s.at)),
            ],
          ),
          el(
            "div",
            {
              class: "muted",
              style:
                "font-size: 12px; line-height: 1.6; padding: 8px; background: var(--bg-1); border-radius: var(--radius-sm); margin-bottom: 8px; font-style: italic;",
            },
            `"${s.snippet}…"`,
          ),
          el("div", { style: "display: flex; gap: 8px;" }, [
            el(
              "button",
              {
                class: "btn btn-tiny btn-danger",
                type: "button",
                onclick: async (ev) => {
                  await withProgress(ev.currentTarget, async () => {
                    const r = await api("contact-dnc-toggle", {
                      contactId: s.contactId,
                      body: { on: true, reason: `opt-out reply: "${s.matchedPhrase}"` },
                    });
                    if (r?.error) toast(r.error, "err");
                    else {
                      toast("✓ Marked do-not-contact", "ok");
                      renderHealth();
                    }
                  });
                },
              },
              "🚫 Mark do-not-contact",
            ),
            el(
              "button",
              {
                class: "btn btn-tiny btn-secondary",
                type: "button",
                onclick: () => showContactDrawer(s.contactId),
              },
              "View contact",
            ),
          ]),
        ]),
      ],
    );
  }

  // "Select all visible" toggle in the toolbar
  const selectAllBox = el("input", {
    type: "checkbox",
    style: "margin-right: 6px;",
    onchange: (e) => {
      const checked = e.target.checked;
      selected.clear();
      // Find every visible suggestion card checkbox and (un)tick it
      const allCheckboxes = document.querySelectorAll(
        '[data-suggestion-id] input[type="checkbox"]',
      );
      allCheckboxes.forEach((cb) => {
        const card = cb.closest("[data-suggestion-id]");
        if (!card || card.style.display === "none") return;
        cb.checked = checked;
        const id = parseInt(card.getAttribute("data-suggestion-id"), 10);
        if (checked) selected.add(id);
      });
      updateBulkBar();
    },
  });

  return el("div", {}, [
    // Top hint + bulk-action toolbar
    el(
      "div",
      {
        style:
          "padding: 10px 12px; margin-bottom: 8px; background: var(--bg-1); border-radius: var(--radius-sm); display: flex; align-items: center; gap: 12px; flex-wrap: wrap;",
      },
      [
        el(
          "label",
          { style: "display: flex; align-items: center; cursor: pointer; user-select: none;" },
          [selectAllBox, el("span", { class: "muted small" }, "Select all visible")],
        ),
        el("span", { class: "muted small", style: "color: var(--text-3);" }, "·"),
        selectedCount,
        el("div", { style: "margin-left: auto; display: flex; gap: 6px;" }, [
          flagAllBtn,
          skipAllBtn,
        ]),
      ],
    ),
    el(
      "div",
      { class: "muted small", style: "padding: 0 0 8px;" },
      `${suggestions.length} contact${suggestions.length === 1 ? "" : "s"} replied with what looks like an opt-out. Review and confirm — flagging stops all future outreach.`,
    ),
    ...suggestions.map(suggestionCard),
  ]);
}

async function renderDncList() {
  const data = await api("dnc-list", { queryString: "?limit=200" }).catch((err) => ({
    error: err.message,
  }));
  if (data?.error) return el("div", { class: "muted" }, `Error: ${data.error}`);
  const contacts = data.contacts || [];

  if (contacts.length === 0) {
    return el("div", { class: "empty-state", style: "padding: 32px;" }, [
      el("div", { class: "empty-state-icon" }, "📋"),
      el("div", { class: "empty-state-title" }, "No DNC entries"),
      el(
        "div",
        { class: "empty-state-hint" },
        "Contacts you mark as do-not-contact appear here. The outreach orchestrator skips them automatically.",
      ),
    ]);
  }

  return el("div", {}, [
    el(
      "div",
      { class: "muted small", style: "padding: 8px 0; margin-bottom: 8px;" },
      `${contacts.length} contact${contacts.length === 1 ? "" : "s"} flagged. The outreach orchestrator skips these on every cycle.`,
    ),
    ...contacts.map((c) =>
      el(
        "div",
        {
          class: "card",
          style: "padding: 12px; margin-bottom: 6px; cursor: pointer;",
          onclick: () => showContactDrawer(c.id),
        },
        [
          el("div", { style: "display: flex; align-items: center; gap: 8px;" }, [
            el("div", { style: "flex: 1;" }, [
              el("div", { class: "primary-cell" }, [
                c.displayName,
                c.company ? el("span", { class: "muted small" }, ` @ ${c.company}`) : null,
              ]),
              c.role ? el("div", { class: "muted small" }, c.role) : null,
              c.reason
                ? el(
                    "div",
                    {
                      class: "muted",
                      style: "font-size: 11px; margin-top: 4px; font-style: italic;",
                    },
                    c.reason,
                  )
                : null,
            ]),
            el("div", { class: "muted small" }, c.dncAt ? fmtDate(c.dncAt) : ""),
            el(
              "button",
              {
                class: "btn btn-tiny btn-secondary",
                type: "button",
                onclick: async (ev) => {
                  ev.stopPropagation();
                  if (!confirm(`Remove ${c.displayName} from the DNC list? Outreach can resume.`))
                    return;
                  await withProgress(ev.currentTarget, async () => {
                    const r = await api("contact-dnc-toggle", {
                      contactId: c.id,
                      body: { on: false },
                    });
                    if (r?.error) toast(r.error, "err");
                    else {
                      toast("Un-flagged", "ok");
                      renderHealth();
                    }
                  });
                },
              },
              "Un-flag",
            ),
          ]),
        ],
      ),
    ),
  ]);
}
