// Export the live sitemap to a portable report file (PDF or Google-Doc-compatible .doc).
// Both formats are generated from one well-styled HTML template so the output is identical.

const { useState: useStateX, useMemo: useMemoX } = React;

const esc = (s) =>
  String(s ?? "")
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;")
    .replace(/'/g, "&#39;");

const KIND_LABEL = { link: "Link", action: "Action", behavior: "Behavior" };

function renderCommentsHTML(list, { kind = "comment" } = {}) {
  if (!list || !list.length) return "";
  return `<ul class="cmt-list">${list
    .map(
      (c) =>
        `<li class="cmt"><span class="cmt-meta"><strong>${esc(c.author)}</strong> · ${esc(
          c.role
        )} · ${esc(c.date)}</span><div class="cmt-body">${esc(c.body)}</div></li>`
    )
    .join("")}</ul>`;
}

function renderSuggestionsHTML(cid, suggestionsByContent) {
  const list = (suggestionsByContent[cid] || []).slice().sort((a, b) => b.upvotes - a.upvotes);
  if (!list.length) return "";
  return `<div class="detail-block">
    <h6>Suggested content drafts (${list.length})</h6>
    ${list
      .map(
        (s) => `
      <div class="sub-card">
        <div class="sub-head">
          <strong>${esc(s.author)}</strong> <span class="sub-role">${esc(s.role)}</span>
          <span class="sub-meta"> · ${esc(s.date)} · <strong>${s.upvotes}</strong> upvote${
          s.upvotes !== 1 ? "s" : ""
        }</span>
        </div>
        <div class="sub-body">${esc(s.body)}</div>
        ${renderCommentsHTML(s.comments)}
      </div>`
      )
      .join("")}
  </div>`;
}

function renderFunctionalityHTML(cid, functionalityByContent, nodes) {
  const list = functionalityByContent[cid] || [];
  if (!list.length) return "";
  return `<div class="detail-block">
    <h6>Intended functionality (${list.length})</h6>
    ${list
      .map((n) => {
        const target = n.targetNodeId && nodes[n.targetNodeId];
        return `
      <div class="sub-card">
        <div class="sub-head">
          <span class="kind-tag kind-${n.kind}">${esc(KIND_LABEL[n.kind] || n.kind)}</span>
          <strong>${esc(n.author)}</strong> <span class="sub-role">${esc(n.role)}</span>
          <span class="sub-meta"> · ${esc(n.date)}</span>
        </div>
        <div class="sub-body">${esc(n.body)}</div>
        ${
          target
            ? `<div class="sub-target"><strong>Target →</strong> ${esc(target.title)} <span class="mono">${esc(target.url || "")}</span></div>`
            : ""
        }
        ${renderCommentsHTML(n.comments)}
      </div>`;
      })
      .join("")}
  </div>`;
}

function buildReportHTML({
  data,
  nodes,
  childOrder,
  commentsByNode,
  suggestionsByContent,
  functionalityByContent,
}) {
  const today = new Date().toLocaleDateString("en-US", {
    year: "numeric",
    month: "long",
    day: "numeric",
  });

  // Totals
  let totalPages = 0, totalSections = 0, totalContent = 0, totalFold = 0;
  let totalComments = 0, totalSuggestions = 0, totalNotes = 0;
  for (const id of Object.keys(nodes)) {
    if (id.startsWith("page:")) totalPages++;
    else if (id.startsWith("sec:")) totalSections++;
    else if (id.startsWith("fold:")) totalFold++;
    else if (id.startsWith("con:")) totalContent++;
  }
  for (const v of Object.values(commentsByNode)) totalComments += v.length;
  for (const v of Object.values(suggestionsByContent)) totalSuggestions += v.length;
  for (const v of Object.values(functionalityByContent)) totalNotes += v.length;

  const css = `
    body { font-family: 'Open Sans', Calibri, Arial, sans-serif; color: #333333; max-width: 780px; margin: 36px auto; padding: 0 24px 60px; line-height: 1.55; }
    .cover { padding-bottom: 14px; border-bottom: 4px solid #7a0019; margin-bottom: 4px; position: relative; }
    .cover::after { content: ""; display: block; width: 120px; height: 4px; background: #ffcc33; margin-top: -4px; }
    .cover-eyebrow { font-size: 11px; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; color: #7a0019; margin-bottom: 6px; }
    h1 { font-size: 32px; color: #333333; margin: 0 0 6px; letter-spacing: -0.01em; }
    .cover-sub { font-size: 14px; color: #5a5a5a; margin: 0 0 18px; }
    .cover-stats { display: flex; flex-wrap: wrap; gap: 16px 28px; font-size: 12px; color: #5a5a5a; margin: 14px 0 32px; padding: 12px 14px; background: #f0efee; border-left: 3px solid #ffcc33; }
    .cover-stats strong { color: #7a0019; font-size: 13px; }
    .toc { background: #f9f7f6; border: 1px solid #d5d6d2; padding: 14px 18px; margin-bottom: 36px; }
    .toc-label { font-size: 11px; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; color: #7a0019; margin-bottom: 8px; }
    .toc ol { margin: 0; padding-left: 20px; font-size: 13px; }
    .toc li { margin: 3px 0; }
    h2 { font-size: 22px; color: #7a0019; margin-top: 42px; padding-bottom: 8px; border-bottom: 2px solid #7a0019; position: relative; }
    h2::after { content: ""; display: block; position: absolute; left: 0; bottom: -2px; width: 70px; height: 2px; background: #ffcc33; }
    .cat-caption { font-size: 12.5px; color: #777677; font-style: italic; margin: 4px 0 18px; }
    .page-block { padding: 18px 20px; margin: 18px 0; border: 1px solid #e3e2df; border-top: 4px solid #7a0019; border-radius: 4px; page-break-inside: avoid; background: #ffffff; }
    .page-block h3 { font-size: 18px; margin: 0 0 6px; color: #333333; }
    .page-url { font-family: 'Courier New', monospace; font-size: 12px; color: #777677; font-weight: 400; margin-left: 8px; }
    .page-meta { font-size: 11.5px; color: #5a5a5a; margin: 0 0 12px; }
    .page-meta strong { color: #7a0019; }
    .page-summary { font-size: 13px; margin: 8px 0; }
    .page-ux { font-size: 12.5px; font-style: italic; color: #5a5a5a; margin: 6px 0; }
    h4 { font-size: 14px; color: #7a0019; margin: 18px 0 8px; padding-left: 8px; border-left: 3px solid #ffcc33; }
    h5 { font-size: 13px; color: #333333; margin: 12px 0 4px; }
    h6 { font-size: 10.5px; color: #b5751f; text-transform: uppercase; letter-spacing: 0.06em; margin: 8px 0 4px; font-weight: 700; }
    .aeo { font-size: 12.5px; color: #5a5a5a; font-style: italic; margin: 4px 0 4px 18px; }
    .fold-item { background: #fff4d4; border-left: 3px solid #b5751f; padding: 8px 12px; margin: 6px 0; }
    .fold-item h5 { margin: 0 0 4px; color: #b5751f; }
    .content-item { background: #f9f7f6; border-left: 3px solid #d5d6d2; padding: 8px 12px; margin: 5px 0; }
    .content-item .ci-title { font-size: 12.5px; }
    .detail-block { margin: 8px 0; padding: 6px 10px; background: #ffffff; border-left: 2px solid #e3e2df; }
    .sub-card { margin: 6px 0; padding: 6px 10px; border-left: 2px solid #f0efee; background: #ffffff; }
    .sub-head { font-size: 11.5px; color: #5a5a5a; margin-bottom: 3px; }
    .sub-head strong { color: #333333; }
    .sub-role { font-size: 10px; text-transform: uppercase; letter-spacing: 0.04em; color: #777677; }
    .sub-meta { color: #777677; }
    .sub-body { font-size: 12.5px; color: #333333; margin: 3px 0; }
    .sub-target { font-size: 11.5px; color: #7a0019; margin-top: 4px; padding-top: 4px; border-top: 1px dashed #e3e2df; }
    .mono { font-family: 'Courier New', monospace; color: #777677; }
    .kind-tag { display: inline-block; font-size: 9.5px; padding: 1px 5px; border: 1px solid currentColor; border-radius: 3px; margin-right: 6px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; }
    .kind-link { color: #7a0019; }
    .kind-action { color: #b5751f; }
    .kind-behavior { color: #5a5a5a; }
    .cmt-list { list-style: none; margin: 4px 0 4px 12px; padding: 0; font-size: 11.5px; }
    .cmt { padding: 4px 8px; margin: 3px 0; background: #f9f7f6; border-left: 2px solid #d5d6d2; }
    .cmt-meta { color: #777677; }
    .cmt-body { color: #333333; margin-top: 2px; }
    .pg-comments { margin-top: 14px; padding-top: 10px; border-top: 1px dashed #d5d6d2; }
    .footer { margin-top: 60px; padding-top: 14px; border-top: 1px solid #d5d6d2; font-size: 10.5px; color: #777677; text-align: center; }
    @media print {
      body { margin: 0 auto; padding: 0 18px 40px; }
      h2 { page-break-before: auto; }
      .page-block { page-break-inside: avoid; }
    }
  `;

  // ---------- Body ----------
  let body = `
    <section class="cover">
      <div class="cover-eyebrow">University of Minnesota · AI Hub</div>
      <h1>Sitemap — Working Draft</h1>
      <p class="cover-sub">Complete export of the AI Hub sitemap: every page, section, content need and above-the-fold item, with all comments, suggested content drafts, and intended-functionality notes.</p>
      <div class="cover-stats">
        <span><strong>${totalPages}</strong> pages</span>
        <span><strong>${totalSections}</strong> sections</span>
        <span><strong>${totalContent}</strong> content needs</span>
        <span><strong>${totalFold}</strong> above-the-fold items</span>
        <span><strong>${totalSuggestions}</strong> content drafts</span>
        <span><strong>${totalNotes}</strong> functionality notes</span>
        <span><strong>${totalComments}</strong> comments</span>
      </div>
      <p class="cover-sub" style="margin-top:0;"><strong>Generated:</strong> ${esc(today)} · <strong>Owner:</strong> ${esc(
    data.meta.ownerTeam
  )}</p>
    </section>
  `;

  // Table of contents
  body += `<nav class="toc"><div class="toc-label">Contents</div><ol>`;
  for (const cat of data.categories) {
    const ids = childOrder[`cat:${cat.id}`] || [];
    if (!ids.length) continue;
    body += `<li><strong>${esc(cat.label)}</strong> — ${ids
      .map((pid) => esc(nodes[pid]?.title || "(missing)"))
      .join(" · ")}</li>`;
  }
  body += `</ol></nav>`;

  // Each category
  for (const cat of data.categories) {
    const catId = `cat:${cat.id}`;
    const pageIds = childOrder[catId] || [];
    if (!pageIds.length) continue;

    body += `<h2>${esc(cat.label)}</h2>`;
    body += `<p class="cat-caption">${esc(cat.caption)}</p>`;

    for (const pid of pageIds) {
      const page = nodes[pid];
      if (!page) continue;

      body += `<article class="page-block">`;
      body += `<h3>${esc(page.title)}<span class="page-url">${esc(page.url || "")}</span></h3>`;
      body += `<p class="page-meta"><strong>Status:</strong> ${esc(
        window.statusLabel(page.status)
      )} · <strong>Owner:</strong> ${esc(page.owner || "—")}</p>`;
      if (page.summary) body += `<p class="page-summary">${esc(page.summary)}</p>`;
      if (page.ux) body += `<p class="page-ux"><strong>UX direction:</strong> ${esc(page.ux)}</p>`;

      if (page.aeo && page.aeo.length) {
        body += `<h4>AEO targets</h4>`;
        body += `<ul class="aeo">${page.aeo.map((q) => `<li>${esc(q)}</li>`).join("")}</ul>`;
      }

      // Fold
      const foldIds = childOrder[`foldlist:${pid}`] || [];
      if (foldIds.length) {
        body += `<h4>Above the fold</h4>`;
        foldIds.forEach((fid, i) => {
          const fn = nodes[fid];
          if (!fn) return;
          const foldComments = commentsByNode[fid] || [];
          body += `<div class="fold-item">
            <h5>${String(i + 1).padStart(2, "0")} · ${esc(fn.title)}</h5>
            ${foldComments.length ? `<div class="pg-comments">${renderCommentsHTML(foldComments)}</div>` : ""}
            ${renderSuggestionsHTML(fid, suggestionsByContent)}
            ${renderFunctionalityHTML(fid, functionalityByContent, nodes)}
          </div>`;
        });
      }

      // Sections
      const sectionIds = childOrder[pid] || [];
      if (sectionIds.length) {
        body += `<h4>Sections</h4>`;
        for (const sid of sectionIds) {
          const sec = nodes[sid];
          if (!sec) continue;
          body += `<h5>${esc(sec.title)}</h5>`;
          if (sec.summary) body += `<p class="page-ux">${esc(sec.summary)}</p>`;
          // Section-level comments
          const secComments = commentsByNode[sid] || [];
          if (secComments.length) {
            body += `<div class="pg-comments">${renderCommentsHTML(secComments)}</div>`;
          }
          const contentIds = childOrder[sid] || [];
          for (const cid of contentIds) {
            const c = nodes[cid];
            if (!c) continue;
            const conComments = commentsByNode[cid] || [];
            body += `<div class="content-item">
              <div class="ci-title">· <strong>${esc(c.title)}</strong></div>
              ${conComments.length ? `<div class="pg-comments">${renderCommentsHTML(conComments)}</div>` : ""}
              ${renderSuggestionsHTML(cid, suggestionsByContent)}
              ${renderFunctionalityHTML(cid, functionalityByContent, nodes)}
            </div>`;
          }
        }
      }

      // Page-level comments
      const pageComments = commentsByNode[pid] || [];
      if (pageComments.length) {
        body += `<div class="pg-comments"><h4>Comments on this page (${pageComments.length})</h4>${renderCommentsHTML(pageComments)}</div>`;
      }

      body += `</article>`;
    }
  }

  body += `<p class="footer">University of Minnesota AI Hub · Working draft · Generated by the sitemap tool</p>`;

  // Wrap in full document — `xmlns:w` markup makes Word/Google Docs treat this
  // as a Word-compatible document when saved with a .doc extension.
  return `<!DOCTYPE html>
<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-html40">
<head>
  <meta charset="utf-8">
  <title>AI Hub Sitemap — Export ${esc(today)}</title>
  <style>${css}</style>
</head>
<body>${body}</body>
</html>`;
}

function downloadBlob(content, filename, mime) {
  const blob = new Blob([content], { type: mime });
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url;
  a.download = filename;
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
  setTimeout(() => URL.revokeObjectURL(url), 1500);
}

function exportAsDoc(args) {
  const html = buildReportHTML(args);
  const date = new Date().toISOString().split("T")[0];
  downloadBlob(html, `AI-Hub-Sitemap-${date}.doc`, "application/msword");
}

function exportAsPdf(args) {
  const html = buildReportHTML(args);

  // Use a hidden iframe so the browser's pop-up blocker doesn't fire
  const iframe = document.createElement("iframe");
  iframe.style.cssText = "position:fixed;top:-9999px;left:-9999px;width:1px;height:1px;border:0;visibility:hidden;";
  document.body.appendChild(iframe);

  const doc = iframe.contentDocument || iframe.contentWindow.document;
  doc.open();
  doc.write(html);
  doc.close();

  let printed = false;
  const doPrint = () => {
    if (printed) return;
    printed = true;
    try {
      iframe.contentWindow.focus();
      iframe.contentWindow.print();
    } catch (e) {
      console.error("Print failed:", e);
    }
    setTimeout(() => {
      if (iframe.parentNode) iframe.parentNode.removeChild(iframe);
    }, 2000);
  };

  // Primary: wait for load event
  iframe.contentWindow.onload = () => setTimeout(doPrint, 400);

  // Fallback: if load already fired before handler attached
  setTimeout(doPrint, 1000);
}

// ---------- UI ----------

function DownloadPanel({
  data,
  nodes,
  childOrder,
  commentsByNode,
  suggestionsByContent,
  functionalityByContent,
}) {
  const stats = useMemoX(() => {
    let comments = 0,
      suggestions = 0,
      notes = 0;
    for (const v of Object.values(commentsByNode)) comments += v.length;
    for (const v of Object.values(suggestionsByContent)) suggestions += v.length;
    for (const v of Object.values(functionalityByContent)) notes += v.length;
    return { comments, suggestions, notes };
  }, [commentsByNode, suggestionsByContent, functionalityByContent]);

  const args = {
    data,
    nodes,
    childOrder,
    commentsByNode,
    suggestionsByContent,
    functionalityByContent,
  };

  return (
    <section className="download-panel">
      <div className="download-inner">
        <div className="download-copy">
          <div className="download-eyebrow">Share & export</div>
          <h3 className="download-title">
            Download all the comments, content and functional notes
          </h3>
          <p className="download-sub">
            One self-contained document with every page, section, content need and
            above-the-fold item — plus all <strong>{stats.comments}</strong> comments,{" "}
            <strong>{stats.suggestions}</strong> content drafts, and{" "}
            <strong>{stats.notes}</strong> functionality notes from the working draft.
          </p>
        </div>
        <div className="download-actions">
          <button className="download-btn pdf" onClick={() => exportAsPdf(args)}>
            <svg width="20" height="20" viewBox="0 0 24 24" aria-hidden="true">
              <path d="M6 2 H14 L20 8 V20 Q20 22 18 22 H6 Q4 22 4 20 V4 Q4 2 6 2 Z"
                    fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinejoin="round" />
              <path d="M14 2 V8 H20" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinejoin="round" />
              <text x="12" y="18" textAnchor="middle" fontFamily="Open Sans, sans-serif"
                    fontSize="6" fontWeight="700" fill="currentColor">PDF</text>
            </svg>
            <span>
              <span className="download-btn-title">Save as PDF</span>
              <span className="download-btn-sub">Print-ready · uses your browser's PDF dialog</span>
            </span>
          </button>
          <button className="download-btn doc" onClick={() => exportAsDoc(args)}>
            <svg width="20" height="20" viewBox="0 0 24 24" aria-hidden="true">
              <path d="M6 2 H14 L20 8 V20 Q20 22 18 22 H6 Q4 22 4 20 V4 Q4 2 6 2 Z"
                    fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinejoin="round" />
              <path d="M14 2 V8 H20" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinejoin="round" />
              <text x="12" y="18" textAnchor="middle" fontFamily="Open Sans, sans-serif"
                    fontSize="6" fontWeight="700" fill="currentColor">DOC</text>
            </svg>
            <span>
              <span className="download-btn-title">Save for Google Docs</span>
              <span className="download-btn-sub">Downloads .doc · upload to Drive → opens as a Doc</span>
            </span>
          </button>
        </div>
      </div>
    </section>
  );
}

Object.assign(window, { DownloadPanel, exportAsDoc, exportAsPdf, buildReportHTML });
