// AI Hub Sitemap — main React app
// Loaded after data.js, which sets window.SITEMAP

const { useState, useEffect, useMemo, useRef, useCallback } = React;

// ---------- Normalize data into a graph ----------
let __uid = 1000;
function uid() { return (++__uid).toString(36); }

function normalize(data) {
  const nodes = {};      // id -> node {id, type, title, parentId, ...}
  const children = {};   // parentId -> [childId, ...]
  const commentsByNode = {}; // nodeId -> [comment, ...]

  // Categories are virtual roots
  for (const cat of data.categories) {
    const catId = `cat:${cat.id}`;
    nodes[catId] = {
      id: catId, type: "category", title: cat.label, caption: cat.caption,
      parentId: null,
    };
    children[catId] = [];
    for (const pageKey of cat.pages) {
      const page = data.pages[pageKey];
      if (!page) continue;
      const pageId = `page:${page.id}`;
      nodes[pageId] = {
        id: pageId, type: "page", title: page.title, url: page.url,
        status: page.status, owner: page.owner, summary: page.summary,
        ux: page.ux, aeo: page.aeo || [],
        parentId: catId,
        categoryId: catId,
        commentCount: page.comments || 0,
      };
      children[catId].push(pageId);
      children[pageId] = [];

      // Fold-zone items become first-class selectable content nodes
      // with their own ordered list under `foldlist:<pageId>`.
      const foldListKey = `foldlist:${pageId}`;
      children[foldListKey] = [];
      (page.aboveFold || []).forEach((text, i) => {
        const fId = `fold:${page.id}:${i}`;
        nodes[fId] = {
          id: fId, type: "content", subtype: "fold",
          title: text, parentId: pageId, pageId, sectionId: null,
        };
        children[foldListKey].push(fId);
      });
      for (const sec of page.sections || []) {
        const secId = `sec:${page.id}:${sec.id}`;
        nodes[secId] = {
          id: secId, type: "section", title: sec.title,
          summary: sec.summary, status: sec.status || page.status,
          parentId: pageId, pageId,
        };
        children[pageId].push(secId);
        children[secId] = [];
        (sec.content || []).forEach((text, i) => {
          const cId = `con:${page.id}:${sec.id}:${i}`;
          nodes[cId] = {
            id: cId, type: "content", title: text,
            parentId: secId, sectionId: secId, pageId,
          };
          children[secId].push(cId);
        });
      }
    }
  }

  // Comments
  for (const [pageKey, list] of Object.entries(data.comments || {})) {
    commentsByNode[`page:${pageKey}`] = list.slice();
  }

  return { nodes, children, commentsByNode };
}

// ---------- Helpers ----------
function descendantIds(nodeId, children, type = null) {
  const out = [];
  const stack = [...(children[nodeId] || [])];
  while (stack.length) {
    const id = stack.pop();
    if (!type || id.startsWith(type + ":")) out.push(id);
    for (const c of children[id] || []) stack.push(c);
  }
  return out;
}

function statusLabel(s) {
  return ({ mvp: "Phase 1 · MVP", phase2: "Phase 2", future: "Future" })[s] || s;
}

// ---------- Icon glyphs ----------
function Glyph({ type }) {
  if (type === "page") {
    return (
      <svg width="18" height="18" viewBox="0 0 18 18" aria-hidden="true">
        <rect x="2" y="2" width="14" height="14" rx="3" fill="#7a0019" />
        <rect x="5.5" y="5.5" width="7" height="1.4" rx="0.7" fill="#ffcc33" opacity="0.95" />
        <rect x="5.5" y="8.3" width="7" height="1.4" rx="0.7" fill="#ffffff" opacity="0.7" />
        <rect x="5.5" y="11.1" width="4.5" height="1.4" rx="0.7" fill="#ffffff" opacity="0.55" />
      </svg>
    );
  }
  if (type === "section") {
    return (
      <svg width="18" height="18" viewBox="0 0 18 18" aria-hidden="true">
        <rect x="2.5" y="2.5" width="13" height="13" rx="2.5" fill="#fff4d4" stroke="#b5751f" strokeWidth="1.5" />
        <rect x="5.5" y="6" width="7" height="1.2" rx="0.6" fill="#b5751f" />
        <rect x="5.5" y="9" width="5" height="1.2" rx="0.6" fill="#b5751f" opacity="0.6" />
      </svg>
    );
  }
  if (type === "content") {
    return (
      <svg width="14" height="14" viewBox="0 0 14 14" aria-hidden="true">
        <circle cx="7" cy="7" r="3" fill="#5a5a5a" />
      </svg>
    );
  }
  return null;
}

function Chevron({ open }) {
  return (
    <svg width="10" height="10" viewBox="0 0 10 10" aria-hidden="true">
      <path d="M3 1.5 L7 5 L3 8.5" stroke="currentColor" strokeWidth="1.6" fill="none" strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  );
}

function DragDots() {
  return (
    <svg width="10" height="14" viewBox="0 0 10 14" aria-hidden="true">
      <g fill="currentColor">
        <circle cx="3" cy="3" r="1.1" />
        <circle cx="7" cy="3" r="1.1" />
        <circle cx="3" cy="7" r="1.1" />
        <circle cx="7" cy="7" r="1.1" />
        <circle cx="3" cy="11" r="1.1" />
        <circle cx="7" cy="11" r="1.1" />
      </g>
    </svg>
  );
}

function SearchIcon() {
  return (
    <svg className="search-icon" viewBox="0 0 14 14" aria-hidden="true">
      <circle cx="6" cy="6" r="4.2" stroke="currentColor" strokeWidth="1.4" fill="none" />
      <path d="M9.2 9.2 L12 12" stroke="currentColor" strokeWidth="1.4" fill="none" strokeLinecap="round" />
    </svg>
  );
}

function CommentGlyph() {
  return (
    <svg width="11" height="11" viewBox="0 0 12 12" aria-hidden="true">
      <path d="M2 2.5 L10 2.5 Q11 2.5 11 3.5 L11 7.5 Q11 8.5 10 8.5 L6 8.5 L3.5 10.5 L4 8.5 L2 8.5 Q1 8.5 1 7.5 L1 3.5 Q1 2.5 2 2.5 Z"
        fill="none" stroke="currentColor" strokeWidth="1.2" strokeLinejoin="round" />
    </svg>
  );
}

Object.assign(window, {
  normalize, descendantIds, statusLabel, uid,
  Glyph, Chevron, DragDots, SearchIcon, CommentGlyph,
});
