/* ═══════════════════════════════════════════════════════════
   CircleThrice — shared components
═══════════════════════════════════════════════════════════ */
const { useState, useEffect, useRef } = React;
const CT = window.CT;

/* ── Icon: references an SVG <symbol> by id ─────────────── */
function Icon({ id, className, style }) {
  return (
    <svg className={className} style={style} viewBox="0 0 16 16" aria-hidden="true">
      <use href={'#' + id} />
    </svg>
  );
}

/* small inline glyphs not in the astrology set */
function LockIcon() {
  return (
    <svg viewBox="0 0 16 16" aria-hidden="true" style={{ overflow: 'visible' }}>
      <rect x="3.5" y="7" width="9" height="6.5" rx="1" fill="none" stroke="currentColor" strokeWidth="1.3" />
      <path d="M5.5 7 V5 a2.5 2.5 0 0 1 5 0 V7" fill="none" stroke="currentColor" strokeWidth="1.3" />
    </svg>
  );
}
function CheckIcon() {
  return (
    <svg viewBox="0 0 16 16" aria-hidden="true" style={{ overflow: 'visible' }}>
      <polyline points="3,8.5 6.5,12 13,4" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  );
}
function DocIcon() {
  return (
    <svg viewBox="0 0 16 16" aria-hidden="true" style={{ overflow: 'visible' }}>
      <path d="M4 1.5 h5 l3 3 v10 h-8 z" fill="none" stroke="currentColor" strokeWidth="1.2" />
      <line x1="6" y1="8" x2="11" y2="8" stroke="currentColor" strokeWidth="1.1" />
      <line x1="6" y1="10.5" x2="11" y2="10.5" stroke="currentColor" strokeWidth="1.1" />
    </svg>
  );
}
function PlayIcon() {
  return (
    <svg viewBox="0 0 16 16" aria-hidden="true" style={{ overflow: 'visible' }}>
      <circle cx="8" cy="8" r="6.5" fill="none" stroke="currentColor" strokeWidth="1.2" />
      <polygon points="6.5,5.5 11,8 6.5,10.5" fill="currentColor" />
    </svg>
  );
}
function CourseIcon() {
  return (
    <svg viewBox="0 0 16 16" aria-hidden="true" style={{ overflow: 'visible' }}>
      <path d="M1.5 5 L8 2 L14.5 5 L8 8 Z" fill="none" stroke="currentColor" strokeWidth="1.2" strokeLinejoin="round" />
      <path d="M4 6.4 V10 c0 1 8 1 8 0 V6.4" fill="none" stroke="currentColor" strokeWidth="1.2" strokeLinejoin="round" />
    </svg>
  );
}
const TYPE_ICON = { Guide: DocIcon, Book: DocIcon, Grimoire: DocIcon, Course: CourseIcon, Video: PlayIcon, PDF: DocIcon };

/* ── Tier badge ─────────────────────────────────────────── */
function TierBadge({ tier }) {
  return (
    <span className={'badge tier-' + tier}>
      <span className="dotmark"></span>{CT.TIER_LABEL[tier]}
    </span>
  );
}
function LockedBadge({ tier }) {
  return (
    <span className="badge locked">
      <span className="lock-glyph"><LockIcon /></span>{CT.TIER_LABEL[tier]}
    </span>
  );
}
function TypeBadge({ type }) {
  return <span className="badge type">{type}</span>;
}
function StatusBadge({ status }) {
  const label = { available: 'Available', full: 'Full', upcoming: 'Upcoming' }[status];
  return <span className={'badge status-' + status}><span className="dotmark"></span>{label}</span>;
}

/* ── Upgrade strip ──────────────────────────────────────── */
function UpgradeStrip({ tier, head, sub }) {
  return (
    <div className="upgrade-strip">
      <div className="us-text">
        <div className="us-head">{head}</div>
        <div className="us-sub">{sub}</div>
      </div>
      <button className="btn btn-upgrade">
        <span className="lock-glyph" style={{ width: 11, height: 11 }}><LockIcon /></span>
        Upgrade to {CT.TIER_LABEL[tier]}
      </button>
    </div>
  );
}

/* ── Header ─────────────────────────────────────────────── */
function Header() {
  return (
    <header className="app-header">
      <div className="brand">
        <span className="brand-mark">Circle<span className="thrice">Thrice</span></span>
        <span className="brand-sub">Member Portal</span>
      </div>
      <div className="header-right">
        <span className="tier-pill"><span className="star"></span>Planning Member</span>
        <button className="acct-btn" title="Account" aria-label="Account">I</button>
      </div>
    </header>
  );
}

/* ── What's New banner ──────────────────────────────────── */
function WhatsNew({ onDismiss }) {
  return (
    <div className="whatsnew">
      <span className="wn-icon"><Icon id="p-moon" /></span>
      <div className="wn-text">
        <span className="wn-head">New Moon in Gemini · The Plan Day Window</span>
        <span className="wn-sep"></span>
        <span className="wn-sub">Sun and Moon conjoin in Gemini at 7:53 PM EST on June 14 — the seed window stays fertile from tonight's dark moon through the first crescent on June 16.</span>
      </div>
      <button className="wn-dismiss" onClick={onDismiss} aria-label="Dismiss">×</button>
    </div>
  );
}

/* ── Sidebar (desktop) ──────────────────────────────────── */
function Sidebar({ active, onNav }) {
  return (
    <nav className="sidebar">
      <div className="nav-list">
        {CT.NAV.map(n => (
          <button
            key={n.id}
            className={'nav-item' + (active === n.id ? ' active' : '')}
            onClick={() => onNav(n.id)}
          >
            <span className="ni-label">{n.label}</span>
          </button>
        ))}
      </div>
    </nav>
  );
}

/* ── Mobile tab bar + More drawer ───────────────────────── */
function TabBar({ active, onNav }) {
  const [drawer, setDrawer] = useState(false);
  const primary = CT.NAV.filter(n => n.primary);            // 4 primary
  const overflow = CT.NAV.filter(n => !n.primary);          // sessions/grimoire/forums
  const moreActive = overflow.some(n => n.id === active);

  return (
    <>
      <nav className="tabbar">
        {primary.map(n => (
          <button key={n.id}
            className={'tab' + (active === n.id ? ' active' : '')}
            onClick={() => onNav(n.id)}>
            <span className="tab-label">{n.label}</span>
          </button>
        ))}
        <button className={'tab' + (moreActive || drawer ? ' active' : '')} onClick={() => setDrawer(true)}>
          <span className="tab-glyph">
            <svg viewBox="0 0 16 16" style={{ overflow: 'visible' }} aria-hidden="true">
              <circle cx="3" cy="8" r="1.4" fill="currentColor" />
              <circle cx="8" cy="8" r="1.4" fill="currentColor" />
              <circle cx="13" cy="8" r="1.4" fill="currentColor" />
            </svg>
          </span>
          <span className="tab-label">More</span>
        </button>
      </nav>

      {drawer && (
        <>
          <div className="drawer-scrim" onClick={() => setDrawer(false)}></div>
          <div className="drawer" role="dialog" aria-label="More sections">
            <div className="drawer-grab"></div>
            {overflow.map(n => (
              <button key={n.id}
                className={'drawer-item' + (active === n.id ? ' active' : '')}
                onClick={() => { onNav(n.id); setDrawer(false); }}>
                <span className="di-label">{n.label}</span>
              </button>
            ))}
          </div>
        </>
      )}
    </>
  );
}

/* ── Footer ─────────────────────────────────────────────── */
function Footer() {
  return (
    <footer className="app-footer">
      <div className="footer-links">
        <a href="#contact">Contact</a>
        <a href="#privacy">Privacy</a>
        <a href="#terms">Terms</a>
      </div>
      <div className="footer-copy">CircleThrice · MMXXVI · Practical magic, well timed.</div>
    </footer>
  );
}

/* ── Toast ──────────────────────────────────────────────── */
function Toast({ msg, onDone }) {
  useEffect(() => {
    const t = setTimeout(onDone, 3600);
    return () => clearTimeout(t);
  }, [msg]);
  if (!msg) return null;
  return (
    <div className="toast-wrap">
      <div className="toast">
        <span className="t-text" dangerouslySetInnerHTML={{ __html: msg }}></span>
      </div>
    </div>
  );
}

/* ── Page header helper ─────────────────────────────────── */
function PageHead({ glyph, kicker, title, desc, topRight }) {
  return (
    <div className="page-head">
      <div className="page-kicker-row">
        <div className="page-kicker">{kicker}</div>
        {topRight}
      </div>
      <h1 className="page-title">{title}</h1>
      {desc && <p className="page-desc">{desc}</p>}
    </div>
  );
}

/* ── Auspice notch: diverging 1–5 sparkline ──────────── */
function AuspiceNotch({ value, max = 5 }) {
  const c = value > 3 ? 'var(--blue)' : value < 3 ? 'var(--inaus)' : 'var(--l-blue)';
  const x0 = 5, x1 = 183, cx = 94;
  const xs = [0, 1, 2, 3, 4].map(i => x0 + i * (x1 - x0) / 4);
  const mx = xs[value - 1];
  return (
    <div className="aus-notch">
      <div className="aus-notch-q">Is today good for magic?</div>
      <svg className="aus-notch-svg" viewBox="0 0 188 22" role="img" aria-label={'Auspice ' + value + ' of ' + max}>
        <line x1={x0} y1="11" x2={x1} y2="11" stroke="var(--rule)" strokeWidth="1.3" />
        {xs.map((x, i) => {
          const h = i === 2 ? 9 : 5.5;
          return <line key={i} x1={x} y1={11 - h / 2} x2={x} y2={11 + h / 2} stroke="var(--rule)" strokeWidth="1.3" />;
        })}
        {mx !== cx && <line x1={cx} y1="11" x2={mx} y2="11" stroke={c} strokeWidth="2" />}
        <circle cx={mx} cy="11" r="4.5" fill={c} />
      </svg>
      <div className="aus-notch-labels">
        <span className="an-bad">Bad</span>
        <span className="an-mid">Neutral</span>
        <span className="an-good">Good</span>
      </div>
    </div>
  );
}

/* ── Modal shell ────────────────────────────────────────── */
function Modal({ onClose, children }) {
  useEffect(() => {
    const h = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', h);
    return () => window.removeEventListener('keydown', h);
  }, []);
  return (
    <div className="modal-scrim" onClick={onClose}>
      <div className="modal fade-in" onClick={e => e.stopPropagation()}>
        {children}
      </div>
    </div>
  );
}

/* ── Custom dropdown (replaces native select) ───────────── */
function Dropdown({ value, options, onChange, ariaLabel }) {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);
  useEffect(() => {
    if (!open) return;
    const onDoc = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    const onKey = (e) => { if (e.key === 'Escape') setOpen(false); };
    document.addEventListener('mousedown', onDoc);
    window.addEventListener('keydown', onKey);
    return () => { document.removeEventListener('mousedown', onDoc); window.removeEventListener('keydown', onKey); };
  }, [open]);
  return (
    <div className={'dropdown' + (open ? ' open' : '')} ref={ref}>
      <button className="dropdown-btn" onClick={() => setOpen(o => !o)}
        aria-haspopup="listbox" aria-expanded={open} aria-label={ariaLabel}>
        {value}<span className="dropdown-caret"></span>
      </button>
      {open && (
        <div className="dropdown-menu fade-in" role="listbox">
          {options.map(opt => (
            <button key={opt} role="option" aria-selected={opt === value}
              className={'dropdown-opt' + (opt === value ? ' sel' : '')}
              onClick={() => { onChange(opt); setOpen(false); }}>
              <span className="dd-dot"></span>{opt}
            </button>
          ))}
        </div>
      )}
    </div>
  );
}

Object.assign(window, {
  Icon, LockIcon, CheckIcon, DocIcon, PlayIcon, CourseIcon, TYPE_ICON,
  TierBadge, LockedBadge, TypeBadge, StatusBadge, UpgradeStrip,
  Header, WhatsNew, Sidebar, TabBar, Footer, Toast, PageHead, Modal, Dropdown, AuspiceNotch,
});
