/* Step 3: Comparison view — Spec Compare */

/* ---------- numeric parsing for best-value highlights ---------- */
function firstNum(str) {
  if (typeof str !== "string") return null;
  const m = str.replace(/,/g, "").match(/-?\d+(\.\d+)?/);
  return m ? parseFloat(m[0]) : null;
}
function rangeSpan(str) {
  if (typeof str !== "string") return null;
  const nums = (str.replace(/,/g, "").match(/-?\d+(\.\d+)?/g) || []).map(parseFloat);
  if (nums.length < 2) return null;
  return Math.abs(nums[1] - nums[0]);
}
/* Returns index of best product for the row, or -1 */
function bestIndex(row, values) {
  if (!row.better) return -1;
  const nums = values.map((v) => (row.better === "widerange" ? rangeSpan(v) : firstNum(v)));
  if (nums.some((n) => n === null)) return -1;
  const uniq = new Set(nums);
  if (uniq.size < 2) return -1;
  const target = row.better === "low" ? Math.min(...nums) : Math.max(...nums);
  // require a single winner
  if (nums.filter((n) => n === target).length !== 1) return -1;
  return nums.indexOf(target);
}

const BEST_LABEL = { high: "Best", low: "Best", widerange: "Widest" };

/* ---------- product switch menu (click model name) ---------- */
function SwapMenu({ product, selection, onSwap, onClose }) {
  const db = window.SPECDB;
  const ref = React.useRef(null);
  React.useEffect(() => {
    const onDoc = (e) => { if (ref.current && !ref.current.contains(e.target)) onClose(); };
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    document.addEventListener("mousedown", onDoc);
    document.addEventListener("keydown", onKey);
    return () => { document.removeEventListener("mousedown", onDoc); document.removeEventListener("keydown", onKey); };
  }, [onClose]);
  return (
    <div className="swapmenu" ref={ref}>
      {db.categories.map((cat) => (
        <div key={cat.id} className="swapmenu-group">
          <div className="swapmenu-title">{cat.name}</div>
          {db.inCategory(cat.id).map((p) => {
            const isCurrent = p.id === product.id;
            const taken = !isCurrent && selection.includes(p.id);
            return (
              <button
                key={p.id}
                className={"swapmenu-item" + (isCurrent ? " swapmenu-item-current" : "")}
                disabled={taken}
                onClick={() => { if (isCurrent) { onClose(); } else { onSwap(product.id, p.id); } }}
              >
                <span className="recent-mark" style={{ background: db.brands[p.brand].color, color: db.brands[p.brand].text }}>{db.brands[p.brand].name[0]}</span>
                <span className="swapmenu-model">{p.model}</span>
                <span className="swapmenu-brand">{taken ? "In compare" : db.brands[p.brand].name}</span>
                {isCurrent ? <span className="swapmenu-check"><Icons.check size={14} /></span> : null}
              </button>
            );
          })}
        </div>
      ))}
    </div>
  );
}

/* ---------- main view ---------- */
function CompareScreen({ selection, onRemove, onSwap, onAddAnother, onBack, tweaks }) {
  const db = window.SPECDB;
  const products = selection.map((id) => db.find(id)).filter(Boolean);
  const [highlightDiffs, setHighlightDiffs] = React.useState(false);
  const [salesMode, setSalesMode] = React.useState(false);
  const edge = React.useMemo(() => computeSalesEdge(products), [selection]);
  const [specQuery, setSpecQuery] = React.useState("");
  const [collapsed, setCollapsed] = React.useState({});
  const [swapFor, setSwapFor] = React.useState(null);

  /* Tesla-style condensing header: drive --hdr-t (0→1) from scroll position */
  const scrollRef = React.useRef(null);
  React.useEffect(() => {
    const el = scrollRef.current;
    if (!el) return;
    let raf = 0;
    const update = () => {
      raf = 0;
      const t = Math.min(1, Math.max(0, el.scrollTop / 120));
      el.style.setProperty("--hdr-t", t.toFixed(3));
      el.classList.toggle("cmp-scroll-condensed", t >= 0.999);
    };
    const onScroll = () => { if (!raf) raf = requestAnimationFrame(update); };
    el.addEventListener("scroll", onScroll, { passive: true });
    update();
    return () => { el.removeEventListener("scroll", onScroll); if (raf) cancelAnimationFrame(raf); };
  }, []);

  const q = specQuery.trim().toLowerCase();
  /* Animated collapse: "closing" plays the exit animation before rows unmount;
     "opening" staggers rows in right after they mount. */
  const [closing, setClosing] = React.useState({});
  const [opening, setOpening] = React.useState({});
  const timersRef = React.useRef({});
  React.useEffect(() => () => Object.values(timersRef.current).forEach(clearTimeout), []);
  const toggleSection = (id) => {
    clearTimeout(timersRef.current[id]);
    if (collapsed[id]) {
      setCollapsed((c) => ({ ...c, [id]: false }));
      setOpening((o) => ({ ...o, [id]: true }));
      timersRef.current[id] = setTimeout(() => setOpening((o) => ({ ...o, [id]: false })), 450);
    } else {
      setClosing((cl) => ({ ...cl, [id]: true }));
      timersRef.current[id] = setTimeout(() => {
        setCollapsed((c) => ({ ...c, [id]: true }));
        setClosing((cl) => ({ ...cl, [id]: false }));
      }, 200);
    }
  };

  const sections = db.sections.map((sec) => {
    const rows = sec.rows
      .map((row) => {
        const values = products.map((p) => p.specs[row.key] ?? "—");
        const keys = values.map((v) => JSON.stringify(v));
        const allSame = keys.every((k) => k === keys[0]);
        const best = -1; /* Best-value badges removed per owner request */
        const matches = !q || row.label.toLowerCase().includes(q) || values.some((v) => String(v).toLowerCase().includes(q));
        return { row, values, allSame, best, matches };
      })
      .filter((r) => r.matches);
    return { sec, rows };
  }).filter((s) => s.rows.length > 0);

  const act = (msg, icon) => () => window.toast(msg, icon);

  return (
    <div className="screen screen-compare" data-screen-label="Step 3 — Comparison">
      <div className="cmp-toolbar">
        <div className="cmp-toolbar-left">
          <button className="backlink" onClick={onBack}><Icons.arrowL size={14} /> Products</button>
          <h2 className="cmp-title">{products[0] ? products[0].specs.categoryName : "Comparison"}</h2>
        </div>
        <div className="cmp-toolbar-mid">
          <div className="searchbox searchbox-sm">
            <Icons.search size={14} />
            <input type="text" placeholder="Jump to a spec…" value={specQuery}
              onChange={(e) => setSpecQuery(e.target.value)} aria-label="Filter specs" />
            {specQuery ? <button className="searchclear" onClick={() => setSpecQuery("")}><Icons.x size={12} /></button> : null}
          </div>
          <button
            className={"togglebtn" + (highlightDiffs ? " togglebtn-on" : "")}
            onClick={() => setHighlightDiffs(!highlightDiffs)}
            aria-pressed={highlightDiffs}
          >
            <span className="togglebtn-track"><span className="togglebtn-knob"></span></span>
            Highlight differences
          </button>
          {edge.available ? (
            <button
              className={"togglebtn" + (salesMode ? " togglebtn-on togglebtn-sales" : "")}
              onClick={() => setSalesMode(!salesMode)}
              aria-pressed={salesMode}
              title="Show where the Honeywell product wins — toggle off before screen-sharing"
            >
              <span className="togglebtn-track"><span className="togglebtn-knob"></span></span>
              Sales mode
            </button>
          ) : null}
        </div>
        <div className="cmp-toolbar-actions">
          <button className="btn btn-outline btn-sm" onClick={act("Comparison PDF generated — check your downloads (simulated)", "doc")}><Icons.doc size={14} /> PDF</button>
          <button className="btn btn-outline btn-sm" onClick={act("Share link copied to clipboard", "link")}><Icons.link size={14} /> Share</button>
          <button className="btn btn-outline btn-sm" onClick={act("Draft email opened with comparison attached (simulated)", "mail")}><Icons.mail size={14} /> Email</button>
          <button className="btn btn-primary btn-sm" onClick={onAddAnother} disabled={selection.length >= 4}><Icons.plus size={14} /> Add product</button>
        </div>
      </div>

      <div className="cmp-scroll" ref={scrollRef}>
        {salesMode && edge.available ? <WhyHeroCard edge={edge} /> : null}
        <table className={"cmp-table" + (tweaks.valueFont === "mono" ? " cmp-mono" : "")}>
          <thead>
            <tr>
              <th className="cmp-corner" aria-label="Specification"></th>
              {products.map((p) => {
                const b = db.brands[p.brand];
                return (
                  <th key={p.id} className="cmp-prodhead">
                    <div className="cmp-prodhead-inner">
                      <div className="cmp-prodhead-top">
                        <div className="cmp-prodhead-badges">
                          {p.status !== "Active" ? <StatusBadge status={p.status} /> : null}
                        </div>
                        <div className="cmp-prodhead-ctrls">
                          <button className="iconbtn" title="Remove" onClick={() => onRemove(p.id)} disabled={products.length <= 2}><Icons.x size={14} /></button>
                        </div>
                      </div>
                      <div className="cmp-prodhead-media">
                        <DeviceImage product={p} h={110} />
                      </div>
                      <div className="cmp-prodhead-id">
                        <span className="brandpill" style={{ background: b.color, color: b.text }}>{b.name}</span>
                        <button
                          className="cmp-modelbtn"
                          title="Switch product"
                          aria-expanded={swapFor === p.id}
                          onClick={() => setSwapFor(swapFor === p.id ? null : p.id)}
                        >
                          {p.model}
                          <span className={"cmp-modelchev" + (swapFor === p.id ? " cmp-modelchev-open" : "")}><Icons.chevD size={15} /></span>
                        </button>
                        <div className="cmp-prodhead-type">{p.typeName}</div>
                      </div>
                      {swapFor === p.id ? (
                        <SwapMenu product={p} selection={selection}
                          onSwap={(oldId, newId) => { setSwapFor(null); onSwap(oldId, newId); }}
                          onClose={() => setSwapFor(null)} />
                      ) : null}
                    </div>
                  </th>
                );
              })}
            </tr>
          </thead>
          {sections.map(({ sec, rows }) => {
            const isCollapsed = collapsed[sec.id] && !q;
            const isClosing = closing[sec.id] && !q;
            const isOpening = opening[sec.id] && !q;
            return (
              <tbody key={sec.id} className={isCollapsed ? "cmp-tbody-collapsed" : ""}>
                <tr className={"cmp-sectionrow" + (isCollapsed ? " cmp-sectionrow-closed" : "")}>
                  <td colSpan={products.length + 1}>
                    <button className="cmp-sectionbtn" onClick={() => toggleSection(sec.id)} aria-expanded={!isCollapsed}>
                      <span className={"cmp-sectionchev" + (isCollapsed ? " cmp-sectionchev-closed" : "")}><Icons.chevD size={14} /></span>
                      {sec.name}
                      <span className="cmp-sectioncount">{rows.length}</span>
                    </button>
                  </td>
                </tr>
                {!isCollapsed && rows.map(({ row, values, allSame, best }, ri) => (
                  <tr key={row.key}
                    style={isOpening ? { animationDelay: Math.min(ri * 28, 220) + "ms" } : undefined}
                    className={
                    "cmp-row" +
                    (isOpening ? " cmp-row-enter" : "") +
                    (isClosing ? " cmp-row-leave" : "") +
                    (highlightDiffs ? (allSame ? " cmp-row-same" : " cmp-row-diff") : "")
                  }>
                    <td className="cmp-label">
                      <Tip text={row.tip}>
                        <span className="cmp-labeltext">{row.label}{row.tip ? <span className="cmp-infodot"><Icons.info size={12} /></span> : null}</span>
                      </Tip>
                    </td>
                    {values.map((v, i) => {
                      const isEdge = salesMode && edge.keys[row.key] && i === edge.heroIdx;
                      return (
                      <td key={i} className={"cmp-cell" + (isEdge ? " cmp-cell-edge" : "")}>
                        {row.type === "aimer" ? (
                          <AimerTile product={products[i]} h={38} />
                        ) : row.type === "bullets" && Array.isArray(v) ? (
                          <ul className="cmp-bullets">{v.map((f, fi) => <li key={fi}>{f}</li>)}</ul>
                        ) : row.key === "status" ? <StatusBadge status={v} /> : <span className="cmp-value">{isEdge ? <span className="edgemark">▲</span> : null}{v}</span>}
                      </td>
                      );
                    })}
                  </tr>
                ))}
              </tbody>
            );
          })}
        </table>
        {sections.length === 0 ? (
          <div className="emptystate">No specs match “{specQuery}”. <button className="btn btn-ghost" onClick={() => setSpecQuery("")}>Clear</button></div>
        ) : null}
      </div>
    </div>
  );
}

Object.assign(window, { CompareScreen });
