// Full-size site shell used by all pages. Responsive to viewport.
// Shares CosmosBG, MacTitleBar, menu bar, taskbar — but full-height and fluid.

const { useMemo: usePSM } = React;

// Responsive hook — returns viewport flags for mobile-first overrides.
// Breakpoints chosen to match existing MenuBar `isNarrow` (980px) — so the
// terminal/windows two-column grid collapses at the same width the menu does.
// `isMobile` (≤600px) hides space-stealing chrome (uptime, handle/time string)
// and triggers single-column collapse on inner 1fr/1fr grids.
//
// Usage: const { isNarrow, isMobile } = useResponsive();
// All consumers (PageShell, MenuBar, Taskbar, ProjectsBody, CV grids, etc.)
// import this from window.useResponsive — kept in one place so breakpoints
// stay consistent across the site.
function useResponsive() {
  const [state, setState] = React.useState(() => {
    if (typeof window === 'undefined' || !window.matchMedia) {
      return { isNarrow: false, isMobile: false };
    }
    return {
      isNarrow: window.matchMedia('(max-width: 980px)').matches,
      isMobile: window.matchMedia('(max-width: 600px)').matches,
    };
  });
  React.useEffect(() => {
    if (typeof window === 'undefined' || !window.matchMedia) return;
    const mqNarrow = window.matchMedia('(max-width: 980px)');
    const mqMobile = window.matchMedia('(max-width: 600px)');
    const update = () => setState({ isNarrow: mqNarrow.matches, isMobile: mqMobile.matches });
    update();
    const add = (mq, fn) => mq.addEventListener ? mq.addEventListener('change', fn) : mq.addListener(fn);
    const rm = (mq, fn) => mq.removeEventListener ? mq.removeEventListener('change', fn) : mq.removeListener(fn);
    add(mqNarrow, update);
    add(mqMobile, update);
    return () => { rm(mqNarrow, update); rm(mqMobile, update); };
  }, []);
  return state;
}
window.useResponsive = useResponsive;

function CosmosBG() {
  const stars = usePSM(() => Array.from({ length: 120 }).map(() => ({
    x: Math.random() * 100, y: Math.random() * 100,
    size: Math.random() > 0.88 ? 2 : 1,
    delay: Math.random() * 5, dur: 2 + Math.random() * 3,
  })), []);
  return (
    <div style={{ position: 'fixed', inset: 0, pointerEvents: 'none', overflow: 'hidden', zIndex: 0 }}>
      {stars.map((s, i) => (
        <div key={i} style={{
          position: 'absolute', left: `${s.x}%`, top: `${s.y}%`,
          width: s.size * 2, height: s.size * 2, background: '#e8e4d4',
          animation: `pxTwinkle ${s.dur}s ${s.delay}s infinite steps(2, end)`,
        }} />
      ))}
      {[{ top: '10%', delay: 5, gap: 20 }, { top: '28%', delay: 15, gap: 28 }, { top: '60%', delay: 9, gap: 32 }].map((sh, i) => (
        <div key={`sh-${i}`} style={{
          position: 'absolute', top: sh.top, left: '-10%', width: 80, height: 2,
          background: 'linear-gradient(90deg, transparent, #e8e4d4 45%, #fff 85%, transparent)',
          opacity: 0,
          animation: `pxShoot ${sh.gap}s ${sh.delay}s infinite`,
          transform: 'rotate(14deg)',
          filter: 'drop-shadow(0 0 3px #fff)',
        }} />
      ))}
    </div>
  );
}

const MAC_STRIPES_S = 'repeating-linear-gradient(0deg, #000 0 1px, transparent 1px 2px)';
function MacTitleBar({ title, active = true }) {
  return (
    <div style={{
      position: 'relative', height: 22,
      background: active ? '#e8e8e8' : '#fff',
      borderBottom: '1px solid #000',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      fontFamily: '"JetBrains Mono", monospace', fontSize: 12, color: '#000',
      overflow: 'hidden',
    }}>
      {active && <div style={{ position: 'absolute', inset: '3px 0', background: MAC_STRIPES_S, opacity: 0.22 }} />}
      <div style={{ position: 'absolute', left: 7, top: 5, width: 12, height: 12, background: '#fff', border: '1px solid #000', zIndex: 2 }} />
      <div style={{ position: 'relative', zIndex: 2, background: active ? '#e8e8e8' : '#fff', padding: '0 10px', letterSpacing: '.02em' }}>
        {title}
      </div>
      <div style={{ position: 'absolute', right: 7, top: 5, width: 12, height: 12, background: '#fff', border: '1px solid #000', zIndex: 2 }}>
        <div style={{ position: 'absolute', inset: 1, border: '1px solid #000' }} />
        <div style={{ position: 'absolute', left: 1, top: 1, right: 4, bottom: 4, background: '#fff', borderRight: '1px solid #000', borderBottom: '1px solid #000' }} />
      </div>
    </div>
  );
}

function RetroWin({ title, accent = '#0000aa', children, id }) {
  const wid = id || (typeof title === 'string' ? 'win-' + title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '') : undefined);
  return (
    <div id={wid} style={{ background: '#fff', border: '1px solid #000', boxShadow: '3px 3px 0 0 #000', fontFamily: '"JetBrains Mono", monospace', marginBottom: 16, scrollMarginTop: 80, transition: 'outline 0.2s' }}>
      <MacTitleBar title={title} />
      <div style={{ height: 3, background: accent }} />
      <div style={{ background: '#fff', color: '#000', padding: '14px 16px', fontSize: 12, lineHeight: 1.6 }}>
        {children}
      </div>
    </div>
  );
}

function MenuBar({ active }) {
  // Top-level items (always visible).
  const topItems = [
    { href: '/', label: 'home' },
    { href: '/cv/', label: 'cv' },
    { href: '/blog/', label: 'blog' },
  ];
  // Project group — flat on wide, dropdown on narrow.
  const projects = [
    { href: '/glam/', label: 'glam.ai' },
    { href: '/happyin-ai/', label: 'happyin.ai' },
    { href: '/ois-gold/', label: 'ois.gold' },
    { href: '/happyin-space/', label: 'happyin.space' },
    { href: '/mclaude/', label: 'mclaude' },
    { href: '/claude-code-config/', label: 'claude-config' },
  ];

  const { isNarrow, isMobile } = useResponsive();
  const [projectsOpen, setProjectsOpen] = React.useState(false);

  // Close dropdown when clicking outside.
  React.useEffect(() => {
    if (!projectsOpen) return;
    const close = (e) => {
      if (!e.target.closest || !e.target.closest('[data-projects-menu]')) {
        setProjectsOpen(false);
      }
    };
    document.addEventListener('click', close);
    return () => document.removeEventListener('click', close);
  }, [projectsOpen]);

  const linkStyle = (label) => ({
    color: active === label ? '#ff5b1f' : '#a99c82',
    textDecoration: 'none',
  });

  const now = new Date();
  const day = now.toLocaleString('en-US', { weekday: 'short' }).toLowerCase();
  const time = now.toTimeString().slice(0, 5);

  const isProjectActive = projects.some(p => p.label === active);

  return (
    <div style={{
      padding: isMobile ? '8px 12px' : '9px 22px', borderBottom: '1px solid #2a2720', background: '#14130f',
      display: 'flex', gap: isMobile ? 12 : 18, alignItems: 'center', flexWrap: 'wrap',
      fontSize: 11, color: '#a99c82', letterSpacing: '.1em', textTransform: 'uppercase',
      position: 'relative', zIndex: 3,
    }}>
      <a href="/" style={{ color: '#ff5b1f', fontWeight: 700, textDecoration: 'none' }}>◆ happyin.work</a>
      {topItems.map(it => (
        <a key={it.label} href={it.href} style={linkStyle(it.label)}>{it.label}</a>
      ))}

      {/* Projects: dropdown on narrow, flat on wide. */}
      {isNarrow ? (
        <div data-projects-menu style={{ position: 'relative' }}>
          <button
            onClick={(e) => { e.stopPropagation(); setProjectsOpen(o => !o); }}
            style={{
              background: 'transparent',
              border: 'none',
              color: isProjectActive ? '#ff5b1f' : '#a99c82',
              fontFamily: 'inherit', fontSize: 'inherit', letterSpacing: 'inherit',
              textTransform: 'uppercase', padding: 0, cursor: 'pointer',
            }}
          >
            my projects {projectsOpen ? '▴' : '▾'}
          </button>
          {projectsOpen && (
            <div style={{
              position: 'absolute', top: 'calc(100% + 8px)', left: 0,
              background: '#14130f', border: '1px solid #2a2720',
              padding: '8px 0', minWidth: 180,
              boxShadow: '4px 4px 0 0 rgba(0,0,0,0.6)',
              zIndex: 10,
            }}>
              {projects.map(p => (
                <a key={p.label} href={p.href} style={{
                  display: 'block', padding: '6px 16px',
                  color: active === p.label ? '#ff5b1f' : '#c4baa3',
                  textDecoration: 'none', fontSize: 11, letterSpacing: '.08em',
                }}>{p.label}</a>
              ))}
            </div>
          )}
        </div>
      ) : (
        <React.Fragment>
          <span style={{ color: '#6b6558', borderLeft: '1px solid #2a2720', paddingLeft: 14 }}>my projects:</span>
          {projects.map(it => (
            <a key={it.label} href={it.href} style={linkStyle(it.label)}>{it.label}</a>
          ))}
        </React.Fragment>
      )}

      <div style={{ flex: 1 }} />
      {/* Hide handle/time on phones — saves the row from wrapping. */}
      {!isMobile && (
        <span style={{ color: '#6b6558' }}>{window.SITE_DATA?.handle || 'happyinhappy'} · {day} {time}</span>
      )}
    </div>
  );
}

// Slugify a window title into an HTML id for in-page navigation.
function winSlug(title) {
  return 'win-' + String(title).toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
}

function Taskbar({ pageLabel, windows }) {
  const { isMobile } = useResponsive();
  const startYear = window.SITE_DATA?.startedYear || 2023;
  const days = Math.floor((Date.now() - new Date(`${startYear}-01-01`).getTime()) / 86400000);
  const years = Math.floor(days / 365);
  const restDays = days - years * 365;
  // On mobile, give buttons a touch-friendly minHeight (~36px) and slightly
  // larger padding. On desktop the original tight padding is preserved.
  const tabBase = {
    padding: isMobile ? '8px 12px' : '2px 10px',
    minHeight: isMobile ? 36 : undefined,
    display: 'inline-flex', alignItems: 'center',
    textDecoration: 'none', color: '#a99c82',
    fontFamily: 'inherit', fontSize: 'inherit',
    cursor: 'pointer',
    whiteSpace: 'nowrap',
  };
  const scrollToWin = (e, slug) => {
    e.preventDefault();
    const el = document.getElementById(slug);
    if (el) {
      el.scrollIntoView({ behavior: 'smooth', block: 'start' });
      // Brief flash to draw the eye.
      const orig = el.style.outline;
      el.style.outline = '2px solid #ff5b1f';
      setTimeout(() => { el.style.outline = orig; }, 800);
    }
  };
  // On mobile: make the row horizontally scrollable so all window-tabs are
  // reachable without wrapping into 3-4 rows that eat vertical space.
  return (
    <div style={{
      borderTop: '1px solid #2a2720', background: '#14130f',
      padding: isMobile ? '6px 10px' : '6px 18px',
      display: 'flex', alignItems: 'center', gap: isMobile ? 6 : 10,
      flexWrap: isMobile ? 'nowrap' : 'wrap',
      overflowX: isMobile ? 'auto' : 'visible',
      fontSize: 11, color: '#a99c82',
      position: 'relative', zIndex: 3,
      // Hide scrollbar visual on mobile — the tabs already imply scroll.
      WebkitOverflowScrolling: 'touch',
    }}>
      <a href="/" style={{ ...tabBase, color: '#ff5b1f', padding: 0 }}>◆</a>
      <a href="#top" onClick={(e) => { e.preventDefault(); window.scrollTo({ top: 0, behavior: 'smooth' }); }}
         style={{ ...tabBase, background: '#2a2720', color: '#e8e4d4' }}>{pageLabel}</a>
      {windows.map((w, i) => (
        <a key={i} href={`#${winSlug(w.title)}`}
           onClick={(e) => scrollToWin(e, winSlug(w.title))}
           style={{ ...tabBase, border: '1px solid #2a2720' }}>{w.title}</a>
      ))}
      <a href="/agents/"
         style={{ ...tabBase, border: '1px solid #2a2720', color: '#6b9b5a' }}
         title="Hi, robot.">agents.txt</a>
      <div style={{ flex: 1, minWidth: isMobile ? 8 : undefined }} />
      {/* Uptime + cursor block hidden on phones — the row is already long. */}
      {!isMobile && <span>uptime: {years}y {restDays}d</span>}
      {!isMobile && <span style={{ width: 9, height: 14, background: '#ff5b1f' }} />}
    </div>
  );
}

function PageShell({ page }) {
  const { crumb, terminalBody, pageLabel, active } = page;
  const { isNarrow, isMobile } = useResponsive();
  // Filter out windows marked hideOnMobile when on mobile.
  // Lets pages omit duplicative right-column blocks on small screens
  // (e.g. projects/ window vs. nav menu projects dropdown).
  const windows = (page.windows || []).filter(w => !(isMobile && w.hideOnMobile));
  return (
    <div style={{
      minHeight: '100vh', background: '#0a0907', color: '#e8e4d4',
      fontFamily: '"JetBrains Mono", monospace',
      display: 'flex', flexDirection: 'column',
      position: 'relative',
    }}>
      <CosmosBG />
      <MenuBar active={active} />

      <div style={{
        padding: isMobile ? '8px 12px' : '10px 22px',
        borderBottom: '1px solid #2a2720',
        fontSize: 11, color: '#6b6558', letterSpacing: '.1em',
        position: 'relative', zIndex: 2, background: 'rgba(20,19,15,0.55)',
      }}>
        <span style={{ color: '#c4baa3' }}>~/</span>
        <span style={{ margin: '0 6px' }}>/</span>
        <span style={{ color: '#e8e4d4' }}>{crumb}</span>
      </div>

      <div style={{
        position: 'relative', zIndex: 2, flex: 1,
        // Narrower viewports: tight padding + zero gap (columns stack).
        padding: isMobile ? '14px 12px 12px' : '28px 32px 24px',
        display: 'grid',
        // Below 980px: collapse 2-column → single column. Terminal first, windows below.
        gridTemplateColumns: isNarrow ? '1fr' : 'minmax(0, 1.45fr) minmax(0, 1fr)',
        gap: isNarrow ? 16 : 28,
        alignItems: 'start',
        maxWidth: 1440, width: '100%', margin: '0 auto', boxSizing: 'border-box',
      }}>
        {/* LEFT (or top on mobile): terminal */}
        <div style={{ background: 'transparent', border: '1px solid #000', boxShadow: '3px 3px 0 0 #000' }}>
          <MacTitleBar title={`${window.SITE_DATA?.handle || 'happyinhappy'}@happyin.work — ${crumb}`} />
          <div style={{ height: 3, background: '#ff5b1f' }} />
          <div style={{
            padding: isMobile ? '16px 14px' : '24px 26px',
            fontSize: isMobile ? 12.5 : 13.5,
            lineHeight: 1.75, color: '#c4baa3',
            background: 'rgba(10,9,7,0.62)',
            // Don't force tall on mobile — content sets the height.
            minHeight: isMobile ? 320 : 560,
          }}>
            {terminalBody}
          </div>
        </div>

        {/* RIGHT (or below on mobile): windows */}
        <div style={{ display: 'flex', flexDirection: 'column' }}>
          {windows.map((w, i) => (
            <RetroWin key={i} title={w.title} accent={w.accent}>
              {w.body}
            </RetroWin>
          ))}
        </div>
      </div>

      <Taskbar pageLabel={pageLabel} windows={windows} />
    </div>
  );
}

window.PageShell = PageShell;
window.MacTitleBar = MacTitleBar;
