// menove-v2-core.jsx, primitives for the v2 single-flow site.
// Depends on window: FB (menove-final), SitePhone/SiteWordmark (menove-site-shared).

/* fbTint fallback, canonical copy lives in menove-circle.jsx; pages that don't load
   the Circle screens still need it for stone tints */
if (!window.fbTint) {
  window.fbTint = (hex, a) => {
    const n = parseInt(hex.slice(1), 16);
    return `rgba(${(n >> 16) & 255}, ${(n >> 8) & 255}, ${n & 255}, ${a})`;
  };
}

/* share-build flag, single-file bundles can't navigate to sibling pages */
const V2_SHARE = !!document.getElementById('__share-assets');

/* asset resolver, in the share build, media is inlined into #__share-assets; resolve through it */
const V2A = (p) => {
  const host = document.getElementById('__share-assets');
  if (!host) return p;
  const el = host.querySelector(`[data-asset="${p}"]`);
  return el ? el.getAttribute('src') : p;
};

/* ---------- cairn, in the three sanctioned treatments ---------- */
function V2Cairn({ variant = 'outline', size = 1, onDark = false, assemble = false, style }) {
  const stones = [['bright', 64, 44], ['steady', 100, 57], ['heavy', 136, 64]];
  const shapes = {
    bright: '50% 50% 50% 50% / 56% 56% 44% 44%',
    steady: '54% 46% 52% 48% / 58% 56% 44% 42%',
    heavy: '58% 42% 56% 44% / 70% 66% 34% 30%',
  };
  const c = variant === 'white' ? '#FFFFFF' : variant === 'aubergine' ? FB.aub : (onDark ? '#FFFFFF' : FB.aub);
  return (
    <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: Math.round(6 * size), ...style }}>
      {stones.map(([s, w, h], i) => (
        <div key={s} className={assemble ? 'rv rv-drop' : undefined} style={{
          ...(assemble ? { '--d': `${.16 + (2 - i) * .22}s` } : {}),
          width: Math.round(w * size), height: Math.round(h * size), borderRadius: shapes[s],
          background: variant === 'outline' ? 'transparent' : c,
          boxShadow: variant === 'outline'
            ? `inset 0 0 0 1.5px ${c}`
            : (variant === 'white' && !onDark ? `inset 0 0 0 1px ${FB.line}, 0 14px 28px -18px rgba(40,8,40,.35)` : 'none'),
        }}></div>
      ))}
    </div>
  );
}

/* ---------- the prominent CTA ---------- */
/* With no href and no onClick, the CTA walks to the beta section: scrolls there
   on the home page (window.__v2GoBeta is set by the app root), or navigates to
   home with the #beta flag from subpages. */
function V2CTA({ children = 'Request beta access', onDark = false, big = false, href, onClick, style }) {
  const fallback = () => {
    if (window.__v2GoBeta) window.__v2GoBeta();
    else window.location.href = V2_HOME + '#beta';
  };
  const inner = (
    <span onClick={!href ? (onClick || fallback) : undefined} style={{
      display: 'inline-flex', alignItems: 'center', gap: 12, borderRadius: 999,
      padding: big ? '20px 44px' : '14px 30px',
      fontFamily: FB.sans, fontSize: big ? 16.5 : 14, fontWeight: 700, letterSpacing: '.01em',
      background: onDark ? '#FFFFFF' : FB.aub, color: onDark ? FB.aub : '#FFFFFF',
      boxShadow: onDark ? '0 24px 54px -22px rgba(0,0,0,.55)' : '0 24px 48px -20px rgba(40,8,40,.6)',
      whiteSpace: 'nowrap', cursor: 'pointer', ...style,
    }}>
      {children}
      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" style={{ width: big ? 17 : 14 }}><path d="M5 12h14M13 6l6 6-6 6" /></svg>
    </span>
  );
  return href && !V2_SHARE ? <a href={href} style={{ textDecoration: 'none' }}>{inner}</a> : inner;
}

/* ---------- fixed nav, flips ink on dark sections ---------- */
const V2_HOME = '/';
const V2_PAGES = { Assessment: '/quiz', Resources: '/resources', Partners: '/partners' };

function V2Nav({ dark, mobile, onSection, page, ctaHref }) {
  const ink = dark ? '#FFFFFF' : FB.ink;
  const links = [
    { l: 'The approach', sec: 1, hash: '#approach' }, { l: 'The app', sec: 3, hash: '#app' },
    { l: 'Assessment' }, { l: 'Resources' }, { l: 'Partners' },
  ];
  // mid widths: drop section links first, then page links, before going fully mobile
  const w = window.innerWidth;
  const visible = links.filter(({ l }) => V2_PAGES[l] ? w >= 900 : w >= 1200);
  const linkStyle = (cur) => ({
    fontSize: 13.5, fontWeight: 600, whiteSpace: 'nowrap', textDecoration: 'none',
    color: cur ? (dark ? '#FFFFFF' : FB.ink) : (dark ? 'rgba(255,255,255,.85)' : FB.body),
    borderBottom: cur ? `2px solid ${dark ? '#FFFFFF' : FB.aub}` : '2px solid transparent', paddingBottom: 2,
    transition: 'color .5s ease', cursor: 'pointer',
  });
  return (
    <div style={{
      position: 'fixed', top: 0, left: 0, right: 0, zIndex: 60,
      display: 'flex', alignItems: 'center', justifyContent: 'space-between',
      padding: mobile ? '18px 22px' : '24px 54px', fontFamily: FB.sans,
      transition: 'color .5s ease', pointerEvents: 'none',
    }}>
      <a href={V2_SHARE ? undefined : V2_HOME} style={{ pointerEvents: 'auto', textDecoration: 'none' }}><SiteWordmark color={ink} size={mobile ? 14 : 16} /></a>
      <div style={{ display: 'flex', alignItems: 'center', gap: mobile ? 14 : 22, pointerEvents: 'auto' }}>
        {!mobile && visible.map(({ l, sec, hash }) => {
          if (V2_PAGES[l]) return V2_SHARE
            ? <span key={l} style={linkStyle(page === l)}>{l}</span>
            : <a key={l} href={V2_PAGES[l]} style={linkStyle(page === l)}>{l}</a>;
          if (onSection) return <span key={l} onClick={() => onSection(sec)} style={linkStyle(false)}>{l}</span>;
          // on subpages, deep-link to the actual section on home (not the hero)
          return V2_SHARE
            ? <span key={l} style={linkStyle(false)}>{l}</span>
            : <a key={l} href={V2_HOME + (hash || '')} style={linkStyle(false)}>{l}</a>;
        })}
        <V2CTA onDark={dark} href={ctaHref}>{mobile ? 'Join the beta' : 'Request beta access'}</V2CTA>
      </div>
    </div>
  );
}

/* ---------- right-edge stone dots ---------- */
function V2DotNav({ count, active, dark, onGo }) {
  return (
    <div style={{ position: 'fixed', right: 22, top: '50%', transform: 'translateY(-50%)', zIndex: 60, display: 'flex', flexDirection: 'column', gap: 14, alignItems: 'center' }}>
      {Array.from({ length: count }).map((_, i) => {
        const c = dark ? '#FFFFFF' : FB.aub;
        const on = i === active;
        return (
          <span key={i} onClick={() => onGo(i)} style={{
            width: on ? 18 : 11, height: on ? 12 : 8,
            borderRadius: '54% 46% 52% 48% / 58% 56% 44% 42%',
            background: on ? c : 'transparent',
            boxShadow: on ? 'none' : `inset 0 0 0 1.5px ${c}`,
            opacity: on ? 1 : .55, cursor: 'pointer',
            transition: 'all .45s cubic-bezier(.22,.61,.21,1)',
          }}></span>
        );
      })}
    </div>
  );
}

/* ---------- hero video, N scenes, sequenced + crossfaded, ~10s loop ---------- */
function V2HeroVideo({ scenes, cut = 3.3 }) {
  // share build may embed only a subset of clips, play what's available
  const host = document.getElementById('__share-assets');
  if (host) scenes = scenes.filter(s => host.querySelector(`[data-asset="${s.src}"]`)) .map(s => s) || scenes;
  if (!scenes.length) scenes = [arguments[0].scenes[0]];
  if (scenes.length === 1) cut = 4.6;
  const [urls, setUrls] = React.useState({});
  const [active, setActive] = React.useState(0);
  const refs = React.useRef([]);
  const reduce = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;

  React.useEffect(() => {
    if (reduce) return;
    const cache = (window.__v2VideoCache = window.__v2VideoCache || {});
    scenes.forEach((s, i) => {
      (cache[s.src] = cache[s.src] || fetch(V2A(s.src)).then(r => r.blob()).then(b => URL.createObjectURL(b)))
        .then(u => setUrls(p => (p[i] ? p : { ...p, [i]: u })))
        .catch(() => {});
    });
  }, []);

  // kick the active video whenever it becomes available or active changes , 
  // autoPlay doesn't fire for elements mounted after the async blob fetch
  React.useEffect(() => {
    const v = refs.current[active];
    if (v && v.paused) v.play().catch(() => {});
  }, [active, urls]);

  const advance = () => {
    setActive(a => {
      const n = (a + 1) % scenes.length;
      const v = refs.current[n];
      if (v) { try { v.currentTime = 0; v.play().catch(() => {}); } catch (e) {} }
      return n;
    });
  };

  return (
    <div style={{ position: 'absolute', inset: 0, overflow: 'hidden', background: FB.aub }}>
      <img src={V2A(scenes[0].poster)} alt="" style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover' }} />
      {!reduce && scenes.map((s, i) => (
        urls[i] ? (
          <video key={s.src} ref={el => { refs.current[i] = el; }} src={urls[i]} muted playsInline autoPlay={i === 0}
            onTimeUpdate={e => { if (i === active && e.target.currentTime >= cut) advance(); }}
            onEnded={() => { if (i === active) advance(); }}
            style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', opacity: i === active ? 1 : 0, transition: 'opacity .7s ease' }}></video>
        ) : null
      ))}
      <div style={{ position: 'absolute', inset: 0, background: 'linear-gradient(180deg, rgba(31,14,42,.30) 0%, rgba(31,14,42,.05) 38%, rgba(31,14,42,.66) 100%)' }}></div>
    </div>
  );
}

/* ---------- the phone, iPhone bezel via IOSDevice, app screens rotating ---------- */
const V2_SCREENS = [
  { k: 'today', label: 'Today', line: 'Ten seconds, once a day. The day gets a shape: bright, steady, tender, or heavy.' },
  { k: 'mona', label: 'Mona', line: 'The companion herself. Tell her about the day in your own words, she keeps what matters, and cites it back with receipts.' },
  { k: 'trail', label: 'The trail', line: 'Thirty stones make a path. A missed day is a quiet outline; it holds your place and says nothing.' },
  { k: 'patterns', label: 'Patterns', line: 'Observations with receipts: “you reported less fog on 3 of 4 walking days.” Never a diagnosis.' },
  { k: 'circle', label: 'The Circle', line: 'Women on the same stretch of trail. Anonymous means anonymous: untraceable, even by us.' },
];

function V2PhoneShow({ scale, idx }) {
  const screens = [
    <FinalScreen state="steady" mode="day" />,
    <M01 />,
    <TrackHome />,
    <PatternsHome />,
    <CircleHome />,
  ];
const BEZEL = 9, W = 390 + BEZEL * 2, H = 844 + BEZEL * 2;
  return (
    <div style={{ width: W * scale, height: H * scale, position: 'relative', flex: 'none' }}>
      <div style={{ transform: `scale(${scale})`, transformOrigin: 'top left', position: 'absolute', top: 0, left: 0 }}>
        <div style={{ background: '#1A161F', borderRadius: 48 + BEZEL, padding: BEZEL, boxShadow: '0 60px 110px -50px rgba(31,14,42,.6)' }}>
          <IOSDevice width={390} height={844} statusBar={false}>
            <div style={{ position: 'relative', width: 390, height: 844, background: FB.paper }}>
              {screens.map((s, i) => (
                <div key={i} style={{ position: 'absolute', inset: 0, opacity: i === idx ? 1 : 0, transition: 'opacity .8s ease', pointerEvents: i === idx ? 'auto' : 'none' }}>{s}</div>
              ))}
            </div>
          </IOSDevice>
        </div>
      </div>
    </div>
  );
}
/* ---------- viewport height hook (for fitting the phone) ---------- */
function useV2Viewport() {
  const [v, setV] = React.useState({ w: window.innerWidth, h: window.innerHeight });
  React.useEffect(() => {
    const f = () => setV({ w: window.innerWidth, h: window.innerHeight });
    window.addEventListener('resize', f);
    return () => window.removeEventListener('resize', f);
  }, []);
  return v;
}

Object.assign(window, { V2A, V2Cairn, V2CTA, V2Nav, V2DotNav, V2HeroVideo, V2PhoneShow, V2_SCREENS, useV2Viewport });
