// dashboard-report-page.js — extracted verbatim from dashboard.js (pure move).

// ── Report page ─────────────────────────────────────────────────

// \u2500\u2500 Per-account performance scoreboard \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
//
// Answers "which of my accounts is producing?" Surfaces sent /
// replied / reply-rate per (account, platform) over the chosen
// window (7d / 30d / 90d). Backed by /api/ops/account-scoreboard.
//
// Why this matters: when a user runs outreach across 3-5 accounts,
// performance varies wildly. Without this view they can't tell
// which account's messaging is working vs. which one is dead.
// One leaderboard reveals it instantly.

let _scoreboardWindow = 7; // days, persisted per session
let _scoreboardSort = { key: "sent", dir: "desc" };

async function renderAccountScoreboard() {
  showLoading("Loading scoreboard\u2026");
  const data = await api("ops-account-scoreboard", {
    queryString: `?days=${_scoreboardWindow}`,
  }).catch(() => ({}));
  if (data?.error) {
    showError(data.error, renderAccountScoreboard);
    return;
  }

  const accounts = Array.isArray(data?.accounts) ? data.accounts : [];
  const total = data?.total || { sent: 0, replied: 0, accountCount: 0, replyRate: 0 };

  // Sort accounts. Reply-rate sort needs a min-volume guard so we
  // don't promote "1 sent, 1 replied = 100%" to the top.
  const sorted = [...accounts].sort((a, b) => {
    const k = _scoreboardSort.key;
    let va, vb;
    if (k === "replyRate") {
      // Min 5 sent to qualify for rate-based sort; otherwise treat as 0.
      va = a.sent >= 5 ? a.replyRate : -1;
      vb = b.sent >= 5 ? b.replyRate : -1;
    } else {
      va = a[k] ?? 0;
      vb = b[k] ?? 0;
    }
    return _scoreboardSort.dir === "asc" ? va - vb : vb - va;
  });

  const platformIcon = (p) =>
    ({
      twitter: "\ud835\udd4f",
      linkedin: "\ud83d\udcbc",
      telegram: "\u2708\ufe0f",
      email: "\ud83d\udce7",
      smtp: "\ud83d\udce7",
    })[p] || "\u00b7";

  // Window selector \u2014 pill buttons that re-fetch on click.
  const windowBtn = (days, label) =>
    el(
      "button",
      {
        type: "button",
        style: [
          "padding:5px 12px",
          "border:1px solid " + (_scoreboardWindow === days ? "rgba(99,102,241,0.6)" : "#2a2a2e"),
          "background:" + (_scoreboardWindow === days ? "rgba(99,102,241,0.18)" : "transparent"),
          "border-radius:14px",
          "color:" + (_scoreboardWindow === days ? "#a5b4fc" : "#cbd5e1"),
          "font-size:11px",
          "cursor:pointer",
          "font-weight:500",
        ].join(";"),
        onclick: () => {
          _scoreboardWindow = days;
          renderAccountScoreboard();
        },
      },
      label,
    );

  // Best account badge \u2014 qualifies if it has >=5 sent and the highest
  // reply rate. Surfaces who's winning.
  const qualifiers = accounts.filter((a) => a.sent >= 5);
  const bestAccount =
    qualifiers.length > 0
      ? qualifiers.reduce((best, a) => (a.replyRate > best.replyRate ? a : best), qualifiers[0])
      : null;

  // Sortable header
  const headerCell = (label, key, align) =>
    el(
      "th",
      {
        style: [
          "padding:8px 12px",
          "text-align:" + (align || "left"),
          "font-size:10px",
          "color:var(--text-2)",
          "text-transform:uppercase",
          "letter-spacing:0.05em",
          "cursor:" + (key ? "pointer" : "default"),
          "user-select:none",
          "border-bottom:1px solid var(--border)",
        ].join(";"),
        onclick: key
          ? () => {
              if (_scoreboardSort.key === key) {
                _scoreboardSort.dir = _scoreboardSort.dir === "asc" ? "desc" : "asc";
              } else {
                _scoreboardSort.key = key;
                _scoreboardSort.dir = "desc";
              }
              renderAccountScoreboard();
            }
          : null,
      },
      [
        el("span", {}, label),
        key === _scoreboardSort.key
          ? el(
              "span",
              { style: "color:#a5b4fc;margin-left:4px;" },
              _scoreboardSort.dir === "asc" ? "\u2191" : "\u2193",
            )
          : null,
      ].filter(Boolean),
    );

  // Per-row rendering. The Sent column renders as a relative bar so
  // the eye can scan volume distribution at a glance.
  const maxSent = Math.max(1, ...accounts.map((a) => a.sent));
  const renderRow = (a, idx) => {
    const isBest =
      bestAccount &&
      a.account_used === bestAccount.account_used &&
      a.platform === bestAccount.platform;
    const rateColor =
      a.sent >= 5
        ? a.replyRate >= 0.25
          ? "#86efac"
          : a.replyRate >= 0.1
            ? "#fde68a"
            : "#fca5a5"
        : "#71717a";
    const ratePct = (a.replyRate * 100).toFixed(a.replyRate >= 0.1 ? 0 : 1);
    return el(
      "tr",
      {
        style:
          "border-bottom:1px solid var(--border);" +
          (isBest ? "background:rgba(34,197,94,0.04);" : ""),
      },
      [
        el(
          "td",
          {
            style:
              "padding:10px 12px;color:var(--text-4);font-family:ui-monospace,monospace;font-size:11px;width:32px;",
          },
          String(idx + 1),
        ),
        el("td", { style: "padding:10px 12px;" }, [
          el("div", { style: "display:flex;align-items:center;gap:8px;" }, [
            el(
              "span",
              { style: "font-size:14px;width:18px;text-align:center;" },
              platformIcon(a.platform),
            ),
            el(
              "span",
              {
                style:
                  "font-size:13px;font-weight:500;color:var(--text-1);font-family:ui-monospace,monospace;",
              },
              a.account_used || "\u2014",
            ),
            isBest
              ? el(
                  "span",
                  {
                    style:
                      "font-size:9px;color:#86efac;background:rgba(34,197,94,0.15);border:1px solid rgba(34,197,94,0.3);padding:1px 6px;border-radius:8px;font-weight:600;letter-spacing:0.04em;text-transform:uppercase;",
                    title: "Highest reply rate among accounts with \u22655 sent",
                  },
                  "\ud83c\udfc6 best",
                )
              : null,
          ]),
        ]),
        el("td", { style: "padding:10px 12px;text-align:right;" }, [
          el(
            "div",
            { style: "display:flex;align-items:center;gap:8px;justify-content:flex-end;" },
            [
              el(
                "span",
                {
                  style:
                    "color:var(--text-1);font-family:ui-monospace,monospace;font-size:13px;font-weight:600;font-variant-numeric:tabular-nums;",
                },
                String(a.sent),
              ),
              // Volume bar
              el(
                "div",
                {
                  style:
                    "width:80px;height:5px;background:rgba(255,255,255,0.05);border-radius:2px;overflow:hidden;",
                },
                [
                  el("div", {
                    style: `width:${(a.sent / maxSent) * 100}%;height:100%;background:linear-gradient(90deg,#3b82f6,var(--green));`,
                  }),
                ],
              ),
            ],
          ),
        ]),
        el(
          "td",
          {
            style:
              "padding:10px 12px;text-align:right;color:var(--text-1);font-family:ui-monospace,monospace;font-size:13px;font-variant-numeric:tabular-nums;",
          },
          String(a.replied),
        ),
        el("td", { style: "padding:10px 12px;text-align:right;" }, [
          el(
            "span",
            {
              style: `color:${rateColor};font-family:ui-monospace,monospace;font-size:13px;font-weight:600;font-variant-numeric:tabular-nums;`,
              title: a.sent < 5 ? "Need \u22655 sent for a stable rate" : "",
            },
            a.sent >= 5 ? `${ratePct}%` : "\u2014",
          ),
          a.sent < 5
            ? el(
                "span",
                {
                  style:
                    "color:var(--text-4);font-size:9px;margin-left:4px;font-family:ui-monospace,monospace;",
                },
                "n/a",
              )
            : null,
        ]),
      ],
    );
  };

  const content = el("div", {}, [
    // Header
    el("div", { class: "page-header" }, [
      el("div", {}, [
        el("div", { class: "page-title" }, "Account scoreboard"),
        el(
          "div",
          { class: "page-subtitle" },
          "Performance per account \u2014 find your winners and underperformers.",
        ),
      ]),
      el(
        "button",
        { class: "btn btn-secondary", type: "button", onclick: renderAccountScoreboard },
        "\u21bb Refresh",
      ),
    ]),

    // Window selector
    el("div", { style: "display:flex;align-items:center;gap:8px;margin-bottom:14px;" }, [
      el("span", { class: "muted small", style: "margin-right:4px;" }, "Window:"),
      windowBtn(1, "Today"),
      windowBtn(7, "7d"),
      windowBtn(30, "30d"),
      windowBtn(90, "90d"),
    ]),

    // Aggregate summary
    el(
      "div",
      {
        style:
          "display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:10px;margin-bottom:18px;",
      },
      [
        statCard(
          "Sent",
          total.sent || 0,
          `last ${_scoreboardWindow}d across ${total.accountCount || 0} accounts`,
        ),
        statCard(
          "Replied",
          total.replied || 0,
          total.sent > 0 ? `${Math.round((total.replied / total.sent) * 100)}% rate` : "",
        ),
        statCard(
          "Best account",
          bestAccount
            ? `${platformIcon(bestAccount.platform)} ${bestAccount.account_used}`
            : "\u2014",
          bestAccount
            ? `${Math.round(bestAccount.replyRate * 100)}% reply rate \u00b7 ${bestAccount.sent} sent`
            : "Need \u22655 sent on at least one account",
        ),
      ],
    ),

    // Table
    accounts.length === 0
      ? el("div", { class: "empty-state" }, [
          el("div", { class: "empty-state-icon" }, "\ud83d\udcca"),
          el("div", { class: "empty-state-title" }, "No outreach activity"),
          el(
            "div",
            { class: "empty-state-hint" },
            `No accounts have sent outreach in the last ${_scoreboardWindow}d. Try a wider window or run a campaign.`,
          ),
        ])
      : el("div", { class: "card", style: "padding:0;overflow:hidden;" }, [
          el("table", { style: "width:100%;border-collapse:collapse;" }, [
            el("thead", {}, [
              el("tr", {}, [
                headerCell("#", null, "left"),
                headerCell("Account", null, "left"),
                headerCell("Sent", "sent", "right"),
                headerCell("Replied", "replied", "right"),
                headerCell("Reply rate", "replyRate", "right"),
              ]),
            ]),
            el("tbody", {}, sorted.map(renderRow)),
          ]),
        ]),

    // Hint footer
    accounts.length > 0
      ? el(
          "div",
          {
            style:
              "margin-top:10px;padding:8px 12px;background:rgba(255,255,255,0.02);border:1px dashed var(--border);border-radius:6px;font-size:11px;color:var(--text-2);line-height:1.5;",
          },
          [
            el("span", {}, "Reply rate uses a 5-sent minimum to filter noise. "),
            el(
              "span",
              { style: "color:var(--text-1);" },
              "Green \u226525%, amber \u226510%, red below.",
            ),
            el("span", {}, " Click headers to sort."),
          ],
        )
      : null,
  ]);

  setContentNode(content);
}

async function renderReport() {
  showLoading("Loading report\u2026");
  const data = await api("report-get").catch(() => ({}));
  if (data?.error) {
    setContent(
      `<div class="empty-state"><div class="empty-state-title">Error</div><div class="empty-state-hint">${escapeHtml(data.error)}</div></div>`,
    );
    return;
  }

  const trendIcon = data.trend > 0 ? "\u2197" : data.trend < 0 ? "\u2198" : "\u2192";
  const trendClass = data.trend > 0 ? "badge-green" : data.trend < 0 ? "badge-red" : "badge-gray";
  const thisActions = data.thisWeek?.actions || 0;
  const thisReplies = data.thisWeek?.replies || 0;
  const replyRate = thisActions > 0 ? ((thisReplies / thisActions) * 100).toFixed(1) : "0";

  const content = el("div", {}, [
    el("div", { class: "page-header" }, [
      el("div", {}, [
        el("div", { class: "page-title" }, "Weekly Report"),
        el("div", { class: "page-subtitle" }, "Performance over the last 7 days vs previous week"),
      ]),
      el(
        "span",
        { class: `badge ${trendClass}`, style: "font-size: 12px; padding: 4px 12px;" },
        `${trendIcon} ${data.trend > 0 ? "+" : ""}${data.trend || 0}%`,
      ),
    ]),

    // Key metrics
    el("div", { class: "stats-grid" }, [
      statCard("Actions", thisActions, [
        el(
          "div",
          { class: "muted", style: "font-size: 10px;" },
          `Last week: ${data.lastWeek?.actions || 0}`,
        ),
      ]),
      statCard("Replies", thisReplies, [
        el("div", { class: "muted", style: "font-size: 10px;" }, `Reply rate: ${replyRate}%`),
      ]),
      statCard("New contacts", data.newContacts || 0, "Added to CRM"),
      statCard("Signals", data.signalsDetected || 0, "Buying signals found"),
      statCard("Campaigns done", data.campaignsCompleted || 0),
    ]),

    // Per-platform breakdown as cards
    (data.platformBreakdown || []).length > 0
      ? el("div", { class: "card" }, [
          el("div", { class: "card-title" }, "Platform Breakdown"),
          el(
            "div",
            {
              style:
                "display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 10px;",
            },
            (data.platformBreakdown || []).map((p) => {
              const pIcons = {
                twitter: "\ud83d\udc26",
                linkedin: "\ud83d\udd17",
                email: "\u2709\ufe0f",
                telegram: "\u2708\ufe0f",
              };
              const pct = thisActions > 0 ? Math.round((p.actions / thisActions) * 100) : 0;
              return el(
                "div",
                {
                  style:
                    "background: var(--bg-0); border: 1px solid var(--border); border-radius: var(--radius-md); padding: 12px;",
                },
                [
                  el(
                    "div",
                    { style: "display: flex; align-items: center; gap: 6px; margin-bottom: 8px;" },
                    [
                      el("span", { style: "font-size: 16px;" }, pIcons[p.platform] || "\u2022"),
                      el(
                        "span",
                        {
                          class: "primary-cell",
                          style: "font-size: 13px; text-transform: capitalize;",
                        },
                        p.platform === "twitter" ? "X / Twitter" : p.platform,
                      ),
                    ],
                  ),
                  el("div", { class: "channel-bar", style: "margin-bottom: 6px;" }, [
                    el("div", { class: "channel-bar-fill healthy", style: `width: ${pct}%` }),
                  ]),
                  el(
                    "div",
                    {
                      style:
                        "display: flex; justify-content: space-between; font-size: 11px; color: var(--text-3);",
                    },
                    [
                      el("span", {}, `${p.actions} actions`),
                      el("span", {}, `${p.outbound || 0} outbound`),
                    ],
                  ),
                ],
              );
            }),
          ),
        ])
      : null,
  ]);
  setContentNode(content);
}
