/* global React, Icon, signOut, useDemoMode, setDemoMode */
// The chrome both portals wear: cream contour sidebar, grouped nav, header
// band, and the sitewide card spotlight.
//
// This used to live inline inside ManagerPortal, which is exactly why the
// admin dashboard drifted into a different product — there was nothing to
// share, so the admin side kept its original flat sidebar while the partner
// side grew a design system. Everything structural now lives here once;
// what differs between the two is passed in.
//
// Slots, rather than props for every possible variation: `aside` takes
// whatever belongs under the wordmark (the manager's course switcher, the
// admin's network status), `headerRight` takes per-screen actions, and
// `children` is the screen itself.

// ─── NavItem — quiet by default; active state reads as a left accent bar
// + faint tint rather than a fully-filled pill, so seven items don't turn
// into seven blocks of color. ──────────────────────────────────────────
function NavItem({ section, active, onClick }) {
  const [hover, setHover] = React.useState(false);
  return (
    <button onClick={onClick} onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}
      title={section.hint || section.label}
      aria-current={active ? 'page' : undefined}
      style={{
        position: 'relative', display: 'flex', alignItems: 'center', gap: 11, textAlign: 'left',
        padding: '9px 12px 9px 14px', borderRadius: 8, border: 'none', cursor: 'pointer',
        background: active ? 'rgba(28,73,42,0.08)' : hover ? 'rgba(28,73,42,0.04)' : 'transparent',
        color: 'var(--forest)', fontSize: 13.5, fontWeight: active ? 700 : 600,
        transition: 'background var(--dur-fast) var(--ease), opacity var(--dur-fast) var(--ease)',
      }}>
      <span style={{
        position: 'absolute', left: 0, top: 6, bottom: 6, width: 2, borderRadius: 2,
        background: 'var(--forest)', opacity: active ? 0.85 : 0,
        transition: 'opacity var(--dur) var(--ease)',
      }}/>
      <span style={{ opacity: active ? 0.95 : 0.6, transition: 'opacity var(--dur-fast) var(--ease)' }}>
        <Icon name={section.icon} size={16}/>
      </span>
      <span style={{ opacity: active ? 1 : 0.72 }}>{section.label}</span>
    </button>
  );
}

// ─── Demo Mode toggle (sidebar) ───────────────────────────────────────
// The store behind this is global, not per-portal, so flipping it in the
// admin sidebar also puts the partner portal into demo — which is the
// behaviour you want when demoing the product end to end.
function DemoToggle() {
  const on = useDemoMode();
  return (
    <button onClick={() => setDemoMode(!on)} style={{
      display: 'flex', alignItems: 'center', gap: 10, width: '100%',
      padding: '9px 11px', borderRadius: 8, border: '1px solid var(--line-strong)',
      background: on ? 'rgba(28,73,42,0.07)' : 'transparent', cursor: 'pointer',
      color: 'var(--forest)', marginTop: 4, transition: 'background var(--dur) var(--ease)',
    }}>
      <span style={{
        width: 28, height: 16, borderRadius: 999, position: 'relative', flexShrink: 0,
        background: on ? 'var(--forest)' : 'rgba(28,73,42,0.2)', transition: 'background var(--dur) var(--ease)',
      }}>
        <span style={{
          position: 'absolute', top: 2, left: on ? 14 : 2, width: 12, height: 12, borderRadius: 999,
          background: 'var(--cream)', transition: 'left var(--dur) var(--ease-out)',
        }}/>
      </span>
      <span style={{ fontFamily: 'var(--font-mono)', fontSize: 10, fontWeight: 600, letterSpacing: '0.06em', textTransform: 'uppercase', opacity: on ? 0.9 : 0.55 }}>
        Demo Mode {on ? '· On' : ''}
      </span>
    </button>
  );
}

// ─── Signed-in footer ─────────────────────────────────────────────────
function PortalUser({ name }) {
  const initials = (name || '').split(' ').filter(Boolean).slice(0, 2)
    .map(s => s[0].toUpperCase()).join('') || '·';
  return (
    <div style={{ borderTop: '1px solid var(--line)', paddingTop: 12, marginTop: 12, display: 'flex', alignItems: 'center', gap: 10, padding: '12px 8px 0' }}>
      <div style={{
        width: 28, height: 28, borderRadius: 999, background: 'var(--forest)', color: 'var(--cream)',
        display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 11, fontWeight: 800, flexShrink: 0,
      }}>{initials}</div>
      <div style={{ fontSize: 12.5, fontWeight: 600, opacity: 0.82, flex: 1, minWidth: 0, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{name}</div>
      <button onClick={signOut} title="Sign out" style={{
        width: 28, height: 28, borderRadius: 8, flexShrink: 0, display: 'flex', alignItems: 'center', justifyContent: 'center',
        background: 'transparent', border: 'none', color: 'var(--forest)', cursor: 'pointer', opacity: 0.55,
        transition: 'opacity var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease)',
      }}
        onMouseEnter={e => { e.currentTarget.style.opacity = 1; e.currentTarget.style.background = 'rgba(28,73,42,0.08)'; }}
        onMouseLeave={e => { e.currentTarget.style.opacity = 0.55; e.currentTarget.style.background = 'transparent'; }}>
        <Icon name="power" size={15}/>
      </button>
    </div>
  );
}

// ─── The spotlight ────────────────────────────────────────────────────
// One listener for every .card in the portal rather than a mousemove
// handler per card. Writes the cursor position relative to the hovered card
// as custom properties that the ::after rule in styles.css reads.
function useCardSpotlight() {
  React.useEffect(() => {
    const onMove = (e) => {
      const card = e.target.closest && e.target.closest('.card');
      if (!card) return;
      const r = card.getBoundingClientRect();
      card.style.setProperty('--spot-x', `${e.clientX - r.left}px`);
      card.style.setProperty('--spot-y', `${e.clientY - r.top}px`);
    };
    document.addEventListener('mousemove', onMove);
    return () => document.removeEventListener('mousemove', onMove);
  }, []);
}

// ─── PortalShell ──────────────────────────────────────────────────────
// scope     — 'manager-portal' | 'admin-portal'; picks the token overrides
// role      — the small label under the wordmark
// groups    — nav group names, in order
// sections  — [{ id, group, label, icon, hint }]
// view/onView — the selected section, controlled by the caller
// aside     — slot under the wordmark (course switcher, network status)
// eyebrow   — small text left of the page title
// headerRight — slot for per-screen actions
// demo      — show the Demo Mode toggle
function PortalShell({
  scope = 'manager-portal', role, groups, sections, view, onView,
  aside, eyebrow, headerRight, demo = true, name, title, children,
}) {
  useCardSpotlight();
  const active = sections.find(s => s.id === view) || sections[0];

  return (
    <div className={scope} style={{ height: '100%', display: 'flex' }}>
      {/* Sidebar — a faint contour texture instead of a flat fill so it
          reads as "course map" rather than "app chrome". */}
      <div className="contour-field" style={{
        width: 240, flexShrink: 0, background: 'var(--cream)', color: 'var(--forest)',
        display: 'flex', flexDirection: 'column', padding: '20px 12px',
        border: 'none', boxShadow: '6px 0 28px rgba(0,0,0,0.4)', position: 'relative', zIndex: 2,
      }}>
        <div style={{ padding: '2px 10px 20px' }}>
          <img src="assets/wordmark-forest.svg" alt="Sandbox" style={{ height: 26, display: 'block' }}/>
          <div style={{ fontFamily: 'var(--font-mono)', fontSize: 10, fontWeight: 600, letterSpacing: '0.1em', textTransform: 'uppercase', color: 'var(--forest)', opacity: 0.5, marginTop: 8 }}>
            {role}
          </div>
        </div>

        {aside}

        <div style={{ display: 'flex', flexDirection: 'column', flex: 1, overflowY: 'auto' }}>
          {groups.map(g => {
            const items = sections.filter(s => s.group === g);
            if (!items.length) return null;
            return (
              <div key={g} style={{ marginBottom: 16 }}>
                <div style={{ fontFamily: 'var(--font-mono)', fontSize: 9, fontWeight: 600, letterSpacing: '0.14em', textTransform: 'uppercase', opacity: 0.36, padding: '0 10px 7px' }}>{g}</div>
                <div style={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
                  {items.map(s => (
                    <NavItem key={s.id} section={s} active={s.id === view} onClick={() => onView(s.id)}/>
                  ))}
                </div>
              </div>
            );
          })}
        </div>

        {demo && <DemoToggle/>}
        <PortalUser name={name}/>
      </div>

      {/* Main */}
      <div style={{ flex: 1, minWidth: 0, display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
        <div style={{ padding: '20px 32px', borderBottom: '1px solid var(--line-strong)', display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', gap: 16 }}>
          <div>
            {/* A drill-down names itself here rather than leaving the header
                describing the list you came from. */}
            <div className="eyebrow">{eyebrow ? `${eyebrow} · ` : ''}{(title ? title.hint : active.hint)}</div>
            <div className="display" style={{ fontSize: 26, color: 'var(--paper)', lineHeight: 1, marginTop: 5 }}>{title ? title.label : active.label}</div>
          </div>
          {headerRight}
        </div>
        <div key={view} className="rise-in" style={{ flex: 1, overflowY: 'auto', padding: '26px 32px' }}>
          {children}
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { PortalShell, NavItem, DemoToggle, PortalUser, useCardSpotlight });
