import type { LiveReportData } from "./schema";

function escapeHtml(value: string): string {
  return value
    .replaceAll("&", "&amp;")
    .replaceAll("<", "&lt;")
    .replaceAll(">", "&gt;")
    .replaceAll('"', "&quot;");
}

function renderList(items: string[]): string {
  if (items.length === 0) {
    return "<p class=\"empty\">None.</p>";
  }
  return `<ul>${items.map((item) => `<li>${escapeHtml(item)}</li>`).join("")}</ul>`;
}

function statusClass(status: string): string {
  return `status-${status.toLowerCase()}`;
}

export function renderLiveReportHtml(data: LiveReportData): string {
  const planRows = data.plans
    .map((plan) => {
      const receipt = plan.planReceipt?.trim() || plan.indexReceipt.trim();
      const mismatch = plan.statusMismatch
        ? `<div class="warn">Index/file status mismatch: index=${plan.indexStatus}, file=${escapeHtml(plan.fileStatus ?? "unknown")}</div>`
        : "";
      return `<tr>
  <td>${escapeHtml(plan.priority)}</td>
  <td><span class="${statusClass(plan.indexStatus)}">${escapeHtml(plan.indexStatus)}</span></td>
  <td><a href="${escapeHtml(plan.href)}">${escapeHtml(plan.title)}</a>${mismatch}</td>
  <td>${escapeHtml(plan.scope)}</td>
  <td>${escapeHtml(plan.worker ?? "—")}</td>
  <td><pre>${escapeHtml(receipt)}</pre></td>
</tr>`;
    })
    .join("\n");

  const workerRows =
    data.activeWorkers.length === 0
      ? "<p class=\"empty\">No ACTIVE plans in index.</p>"
      : `<table>
  <thead><tr><th>Plan</th><th>Worker</th><th>Receipt</th></tr></thead>
  <tbody>${data.activeWorkers
    .map(
      (worker) => `<tr>
  <td><a href="${escapeHtml(worker.href)}">${escapeHtml(worker.planTitle)}</a></td>
  <td>${escapeHtml(worker.worker)}</td>
  <td><pre>${escapeHtml(worker.receipt)}</pre></td>
</tr>`,
    )
    .join("\n")}</tbody>
</table>`;

  const blockerRows =
    data.blockers.length === 0
      ? "<p class=\"empty\">No BLOCKED plans in index.</p>"
      : `<table>
  <thead><tr><th>Plan</th><th>Blocker receipt</th></tr></thead>
  <tbody>${data.blockers
    .map(
      (blocker) => `<tr>
  <td><a href="${escapeHtml(blocker.href)}">${escapeHtml(blocker.planTitle)}</a></td>
  <td><pre>${escapeHtml(blocker.receipt)}</pre></td>
</tr>`,
    )
    .join("\n")}</tbody>
</table>`;

  const sessionRows =
    data.activeSessions.length === 0
      ? "<p class=\"empty\">No open agent-session ledger records.</p>"
      : `<table>
  <thead><tr><th>Ledger</th><th>Runtime</th><th>Host</th><th>Started</th><th>Launched by</th><th>Worktree</th></tr></thead>
  <tbody>${data.activeSessions
    .map(
      (session) => `<tr>
  <td>${escapeHtml(session.ledgerId)}</td>
  <td>${escapeHtml(session.runtime)}</td>
  <td>${escapeHtml(session.host)}</td>
  <td>${escapeHtml(session.startedAt)}</td>
  <td>${escapeHtml(session.launchedBy ?? "—")}</td>
  <td>${escapeHtml(session.worktree ?? "—")}</td>
</tr>`,
    )
    .join("\n")}</tbody>
</table>`;

  return `<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>Overdeck live session report</title>
  <style>
    :root {
      color-scheme: light dark;
      --bg: #f7f7f8;
      --fg: #111827;
      --muted: #4b5563;
      --border: #d1d5db;
      --card: #ffffff;
      --warn: #92400e;
      --warn-bg: #fef3c7;
    }
    @media (prefers-color-scheme: dark) {
      :root {
        --bg: #0b1020;
        --fg: #e5e7eb;
        --muted: #9ca3af;
        --border: #374151;
        --card: #111827;
        --warn: #fbbf24;
        --warn-bg: #3f2d0d;
      }
    }
    body {
      margin: 0;
      font: 14px/1.5 system-ui, sans-serif;
      background: var(--bg);
      color: var(--fg);
    }
    main {
      max-width: 1200px;
      margin: 0 auto;
      padding: 24px;
    }
    h1, h2 { line-height: 1.2; }
    .meta, .empty { color: var(--muted); }
    section {
      background: var(--card);
      border: 1px solid var(--border);
      border-radius: 12px;
      padding: 16px;
      margin: 16px 0;
    }
    table {
      width: 100%;
      border-collapse: collapse;
    }
    th, td {
      border-bottom: 1px solid var(--border);
      padding: 8px;
      vertical-align: top;
      text-align: left;
    }
    pre {
      margin: 0;
      white-space: pre-wrap;
      word-break: break-word;
      font: inherit;
    }
    a { color: inherit; }
    .warn {
      margin-top: 6px;
      padding: 6px 8px;
      border-radius: 8px;
      background: var(--warn-bg);
      color: var(--warn);
      font-size: 12px;
    }
    .status-active { font-weight: 700; }
    .status-blocked { font-weight: 700; color: #b45309; }
    .status-done { color: #047857; }
  </style>
</head>
<body>
  <main>
    <h1>Overdeck live session report</h1>
    <p class="meta">Generated at ${escapeHtml(data.generatedAt)} from ${escapeHtml(data.indexPath)} · source revision ${escapeHtml(data.sourceRevision)}</p>
    <section>
      <h2>Active workers</h2>
      ${workerRows}
    </section>
    <section>
      <h2>Blockers</h2>
      ${blockerRows}
    </section>
    <section>
      <h2>Open agent sessions</h2>
      ${sessionRows}
    </section>
    <section>
      <h2>Plan index</h2>
      <table>
        <thead>
          <tr>
            <th>Priority</th>
            <th>Status</th>
            <th>Plan</th>
            <th>Scope</th>
            <th>Worker</th>
            <th>Receipt</th>
          </tr>
        </thead>
        <tbody>
          ${planRows}
        </tbody>
      </table>
    </section>
    <section>
      <h2>Warnings</h2>
      ${renderList(data.warnings)}
    </section>
  </main>
</body>
</html>
`;
}
