// talon-chrome.jsx — TopBar, RegionSwitcher, ZoomControls, ArticlePanel, overlays.
const { useState: _uS, useRef: _uR, useEffect: _uE } = React;

// ── TopBar + RegionSwitcher ────────────────────────────────────
function RegionSwitcher({ regions, activeId, onPick }) {
  const [open, setOpen] = _uS(false);
  const ref = _uR(null);
  _uE(() => {
    const h = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    window.addEventListener("mousedown", h);
    return () => window.removeEventListener("mousedown", h);
  }, []);
  if (regions.length < 2) return null;
  const active = regions.find((r) => r.id === activeId);
  return (
    <div className="region-switcher" ref={ref}>
      <button className="region-btn" onClick={() => setOpen((o) => !o)} aria-haspopup="true" aria-expanded={open}>
        <span>{active.name}</span>
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor"
             strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"
             style={{ transform: open ? "rotate(180deg)" : "none", transition: "transform .18s" }}>
          <path d="M6 9l6 6 6-6" />
        </svg>
      </button>
      {open && (
        <div className="region-menu" role="menu">
          {regions.map((r) => (
            <button key={r.id} role="menuitem"
                    className={"region-row" + (r.id === activeId ? " is-active" : "")}
                    onClick={() => { onPick(r.id); setOpen(false); }}>
              <span className="region-dot" style={{ opacity: r.id === activeId ? 1 : 0 }} />
              <span>{r.name}</span>
              {r.treatment === "placeholder" && <span className="region-pending">art pending</span>}
            </button>
          ))}
        </div>
      )}
    </div>
  );
}

function TopBar({ regions, activeId, onPick, onHome }) {
  return (
    <header className="top-bar">
      <button className="site-mark" onClick={onHome} aria-label="Talon — reset view">
        <TalonMark size={20} weight={1.7} />
        <span className="site-name">Talon</span>
      </button>
      <div className="top-spacer" />
      <RegionSwitcher regions={regions} activeId={activeId} onPick={onPick} />
    </header>
  );
}

// ── ZoomControls ───────────────────────────────────────────────
function ZoomControls({ zoom, min, max, onZoom, onReset }) {
  const atMax = zoom >= max - 0.001, atMin = zoom <= min + 0.001;
  return (
    <div className="zoom-controls" role="group" aria-label="Zoom">
      <button onClick={() => onZoom(1.25)} disabled={atMax} aria-label="Zoom in">
        <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><path d="M12 5v14M5 12h14" /></svg>
      </button>
      <span className="zoom-divider" />
      <button onClick={() => onZoom(0.8)} disabled={atMin} aria-label="Zoom out">
        <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><path d="M5 12h14" /></svg>
      </button>
      <span className="zoom-divider" />
      <button onClick={onReset} aria-label="Reset view">
        <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="3" /><path d="M12 4v2M12 18v2M4 12h2M18 12h2" /></svg>
      </button>
    </div>
  );
}

// ── ArticlePanel ───────────────────────────────────────────────
function ArticlePanel({ poi, region, regionName, accent, onClose, onSelectRelated, returnFocusRef }) {
  const [render, setRender] = _uS(!!poi);
  const [shown, setShown] = _uS(false);
  const closeRef = _uR(null);
  const bodyRef = _uR(null);

  // mount/unmount with slide transition
  _uE(() => {
    if (poi) {
      setRender(true);
      const id = requestAnimationFrame(() => requestAnimationFrame(() => setShown(true)));
      const f = setTimeout(() => closeRef.current && closeRef.current.focus(), 60);
      if (bodyRef.current) bodyRef.current.scrollTop = 0;
      return () => { cancelAnimationFrame(id); clearTimeout(f); };
    } else {
      setShown(false);
      const t = setTimeout(() => setRender(false), prefersReduced() ? 0 : 300);
      return () => clearTimeout(t);
    }
  }, [poi]);

  _uE(() => {
    const h = (e) => { if (e.key === "Escape" && poi) onClose(); };
    window.addEventListener("keydown", h);
    return () => window.removeEventListener("keydown", h);
  }, [poi, onClose]);

  if (!render) return null;
  const data = poi || ArticlePanel._last || {};
  if (poi) ArticlePanel._last = poi; // keep last for exit animation
  const Icon = iconFor(data.category);
  const cat = (data.category || "place").replace(/^\w/, (c) => c.toUpperCase());
  const related = (data.related || [])
    .map((id) => region.pois.find((p) => p.id === id)).filter(Boolean);

  return (
    <aside className={"article-panel" + (shown ? " is-open" : "")}
           style={{ ["--accent"]: accent.base, ["--accent-bright"]: accent.bright }}
           aria-label={data.title} role="dialog" aria-modal="false">
      <div className="panel-head">
        <button ref={closeRef} className="panel-close" onClick={onClose} aria-label="Close">
          <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round"><path d="M6 6l12 12M18 6L6 18" /></svg>
        </button>
      </div>
      <div className="panel-scroll" ref={bodyRef}>
        <div className="panel-hero">
          {data.hero ? (
            <img src={data.hero} alt="" className="hero-img" />
          ) : (
            <div className="hero-glyph">
              <Icon size={56} />
              <span className="hero-stripes" />
            </div>
          )}
        </div>
        <div className="panel-title-block">
          <h1 className="panel-title">{data.title}</h1>
          <p className="panel-sub">{data.subtitle ? data.subtitle + " · " : cat + " · "}{regionName}</p>
        </div>
        {data.tags && data.tags.length > 0 && (
          <div className="tag-row">
            {data.tags.map((t) => <span key={t} className="tag-chip">{t}</span>)}
          </div>
        )}
        <div className="panel-body prose">
          {(data.body || []).map((blk, i) => (
            <React.Fragment key={i}>
              {blk.h && <h2>{blk.h}</h2>}
              <p dangerouslySetInnerHTML={{ __html: mdInline(blk.p) }} />
            </React.Fragment>
          ))}
        </div>
        {related.length > 0 && (
          <div className="related">
            <div className="related-label">Linked entries</div>
            {related.map((r) => {
              const RI = iconFor(r.category);
              return (
                <button key={r.id} className="related-row" onClick={() => onSelectRelated(r)}>
                  <span className="related-icon"><RI size={15} /></span>
                  <span>{r.title}</span>
                  <svg className="related-arrow" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M9 6l6 6-6 6" /></svg>
                </button>
              );
            })}
          </div>
        )}
      </div>
    </aside>
  );
}
// tiny inline markdown: _em_ and **strong**
function mdInline(s) {
  return (s || "")
    .replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")
    .replace(/\*\*([^*]+)\*\*/g, "<strong>$1</strong>")
    .replace(/_([^_]+)_/g, "<em>$1</em>");
}

// ── Loading + Desktop guard ────────────────────────────────────
function LoadingMark() {
  return (
    <div className="loading-screen">
      <div className="loading-glyph"><TalonMark size={40} weight={1.4} /></div>
      <div className="loading-text">Charting Talon…</div>
    </div>
  );
}
function DesktopGuard() {
  return (
    <div className="desktop-guard">
      <TalonMark size={32} weight={1.4} />
      <p>Talon Map is desktop-only for now.<br />Visit on a larger screen.</p>
    </div>
  );
}

Object.assign(window, { TopBar, RegionSwitcher, ZoomControls, ArticlePanel, LoadingMark, DesktopGuard });
