// ============================================================
// APP — boot, chrome, cursor (hard-coded cinematic preset)
// ============================================================

// One look, locked in:
// cyan accent · live nodes (mesh) · max intensity · Playfair + Poppins · grain on

const ACCENT_HEX = {
  cyan:     { c: '#22d3ee', s: '#67e8f9', d: '#0891b2', g: 'rgba(34,211,238,0.45)', f: 'rgba(34,211,238,0.08)' },
  violet:   { c: '#8b5cf6', s: '#a78bfa', d: '#6d28d9', g: 'rgba(139,92,246,0.45)', f: 'rgba(139,92,246,0.08)' },
  blue:     { c: '#3b82f6', s: '#60a5fa', d: '#1e40af', g: 'rgba(59,130,246,0.45)',  f: 'rgba(59,130,246,0.08)' },
  spectrum: { c: '#22d3ee', s: '#a78bfa', d: '#3b82f6', g: 'rgba(167,139,250,0.45)', f: 'rgba(34,211,238,0.08)' },
  mono:     { c: '#e5e7eb', s: '#f5f6f8', d: '#9ca3af', g: 'rgba(229,231,235,0.30)', f: 'rgba(229,231,235,0.06)' },
};

const TYPO_PRESETS = {
  cinematic: {
    display: "'Playfair Display', 'Times New Roman', serif",
    sans:    "'Poppins', ui-sans-serif, system-ui, sans-serif",
    mono:    "'JetBrains Mono', ui-monospace, monospace",
    google:  "Playfair+Display:ital,wght@0,400;0,600;1,400|Poppins:wght@300;400;500;600|JetBrains+Mono:wght@300;400;500"
  },
  editorial: {
    display: "'Instrument Serif', 'Times New Roman', serif",
    sans:    "'Poppins', ui-sans-serif, system-ui, sans-serif",
    mono:    "'JetBrains Mono', ui-monospace, monospace",
    google:  "Instrument+Serif:ital@0;1|Poppins:wght@300;400;500;600|JetBrains+Mono:wght@300;400;500"
  },
  minimal: {
    display: "'Fraunces', serif",
    sans:    "'Poppins', ui-sans-serif, system-ui, sans-serif",
    mono:    "'JetBrains Mono', ui-monospace, monospace",
    google:  "Fraunces:opsz,wght,SOFT@9..144,300..600,30|Poppins:wght@300;400;500;600|JetBrains+Mono:wght@300;400;500"
  },
  plex: {
    display: "'IBM Plex Serif', serif",
    sans:    "'IBM Plex Sans', sans-serif",
    mono:    "'IBM Plex Mono', monospace",
    google:  "IBM+Plex+Serif:ital,wght@0,400;0,500;1,400|IBM+Plex+Sans:wght@300;400;500;600|IBM+Plex+Mono:wght@300;400;500"
  }
};

function applyAccent(name) {
  const a = ACCENT_HEX[name] || ACCENT_HEX.cyan;
  const r = document.documentElement;
  r.style.setProperty('--accent',       a.c);
  r.style.setProperty('--accent-soft',  a.s);
  r.style.setProperty('--accent-deep',  a.d);
  r.style.setProperty('--accent-glow',  a.g);
  r.style.setProperty('--accent-faint', a.f);
  if (window.__neural) window.__neural.setPalette(name);
}

function applyTypography(name) {
  const p = TYPO_PRESETS[name] || TYPO_PRESETS.cinematic;
  const r = document.documentElement;
  r.style.setProperty('--f-display', p.display);
  r.style.setProperty('--f-sans',    p.sans);
  r.style.setProperty('--f-mono',    p.mono);
}

function applyIntensity(name) {
  const map = { restrained: 0.5, refined: 1.0, max: 1.6 };
  if (window.__neural) window.__neural.setIntensity(map[name] ?? 1);
  document.documentElement.style.setProperty('--intensity', map[name] ?? 1);
}

function applyConcept(name) {
  if (window.__neural) window.__neural.setConcept(name);
}

function applyTheme(light) {
  document.documentElement.setAttribute('data-theme', light ? 'light' : 'dark');
}

// ──────────────────────────────────────────────────────────
// BOOT LOADER
// ──────────────────────────────────────────────────────────
function BootLoader({ onDone }) {
  const [progress, setProgress] = React.useState(0);
  const [log, setLog] = React.useState('initializing');
  const [gone, setGone] = React.useState(false);

  React.useEffect(() => {
    const stages = [
      { at: 0.10, label: 'loading shaders' },
      { at: 0.25, label: 'mounting neural runtime' },
      { at: 0.40, label: 'binding cloud cluster' },
      { at: 0.55, label: 'calibrating inference graph' },
      { at: 0.70, label: 'syncing telemetry' },
      { at: 0.85, label: 'compiling render pipeline' },
      { at: 0.98, label: 'ready' },
    ];
    const TOTAL = 2200; // ms
    const start = performance.now();
    let raf;
    let done = false;
    const tick = (now) => {
      const elapsed = now - start;
      const p = Math.min(1, elapsed / TOTAL);
      const pct = Math.round(p * 100);
      setProgress(pct);
      const stage = [...stages].reverse().find(s => p >= s.at);
      if (stage) setLog(stage.label);
      if (p < 1) {
        raf = requestAnimationFrame(tick);
      } else if (!done) {
        done = true;
        setLog('online');
        setTimeout(() => {
          setGone(true);
          setTimeout(onDone, 800);
        }, 250);
      }
    };
    raf = requestAnimationFrame(tick);

    // Failsafe — if rAF stalls, force completion after 6s of wall-clock
    const failsafe = setTimeout(() => {
      if (done) return;
      done = true;
      setProgress(100);
      setLog('online');
      setGone(true);
      setTimeout(onDone, 400);
    }, 6000);

    return () => {
      cancelAnimationFrame(raf);
      clearTimeout(failsafe);
    };
  }, []);

  return (
    <div className={"boot" + (gone ? " gone" : "")}>
      <div className="boot-grid"></div>
      <div className="boot-core">
        <div className="boot-logo">
          <img src="assets/mp_logo_square.jpg" alt="MP" className="boot-logo-img" />
          <svg viewBox="-44 -44 88 88" className="boot-logo-orbit">
            <circle className="ring"   cx="0" cy="0" r="40" />
            <circle className="ring ring-2" cx="0" cy="0" r="36" />
            <circle cx="40" cy="0" r="1.5" fill="var(--accent)" />
            <circle cx="-40" cy="0" r="1.5" fill="var(--accent)" />
            <circle cx="0" cy="40" r="1.5" fill="var(--accent)" />
            <circle cx="0" cy="-40" r="1.5" fill="var(--accent)" />
          </svg>
        </div>
        <div className="boot-status">
          <span>MP · ARCH</span>
          <span className="ok">{progress.toString().padStart(3, '0')}%</span>
        </div>
        <div className="boot-bar">
          <div className="boot-bar-fill" style={{ width: progress + '%' }}></div>
        </div>
        <div className="boot-log">
          ▸ <span>{log}</span>
        </div>
      </div>
    </div>
  );
}

// ──────────────────────────────────────────────────────────
// CHROME — top + bottom
// ──────────────────────────────────────────────────────────
function Chrome() {
  const [time, setTime] = React.useState('');
  React.useEffect(() => {
    const tick = () => {
      const d = new Date();
      const t = d.toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit', second: '2-digit', timeZone: 'Asia/Singapore' });
      setTime(t + ' SGT');
    };
    tick();
    const i = setInterval(tick, 1000);
    return () => clearInterval(i);
  }, []);

  return (
    <React.Fragment>
      <header className="chrome-top">
        <a className="brand-mark" href="#top">
          <span className="brand-glyph">
            <img src="assets/mp_logo_square.jpg" alt="Mayer Putra" />
          </span>
          <span className="brand-name">MP · Cloud + AI Architect</span>
        </a>
        <nav className="chrome-nav">
          <a href="#identity">01 Identity</a>
          <a href="#infrastructure">02 Infrastructure</a>
          <a href="#intelligence">03 Intelligence</a>
          <a href="#horizon">04 Horizon</a>
          <a href="#contact">05 Engage</a>
        </nav>
        <div className="chrome-status">
          <span className="status-dot"></span>
          <span>{time}</span>
        </div>
      </header>
      <div className="chrome-bottom">
        <span className="chrome-secure">
          <span className="status-dot small"></span>
          Confidential engagement · NDA on first contact
        </span>
      </div>
    </React.Fragment>
  );
}

// ──────────────────────────────────────────────────────────
// CURSOR LIGHT — refined
// ──────────────────────────────────────────────────────────
function CursorLight() {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const el = ref.current;
    if (!el) return;
    let x = -100, y = -100, tx = -100, ty = -100;
    const onMove = (e) => { tx = e.clientX; ty = e.clientY; };
    const onOver = (e) => {
      const t = e.target.closest('a, button, .magnet, [data-magnetic], .infra-row, .cert-cell, .horizon-cell, .partner');
      if (t) el.classList.add('hovering');
      else el.classList.remove('hovering');
    };
    window.addEventListener('mousemove', onMove);
    window.addEventListener('mouseover', onOver);

    let raf;
    const loop = () => {
      x += (tx - x) * 0.55;
      y += (ty - y) * 0.55;
      el.style.transform = `translate(${x}px, ${y}px)`;
      raf = requestAnimationFrame(loop);
    };
    raf = requestAnimationFrame(loop);
    return () => {
      window.removeEventListener('mousemove', onMove);
      window.removeEventListener('mouseover', onOver);
      cancelAnimationFrame(raf);
    };
  }, []);
  return <div className="cursor-light" ref={ref}></div>;
}

// ──────────────────────────────────────────────────────────
// PROGRESS RAIL
// ──────────────────────────────────────────────────────────
function ProgressRail() {
  const fillRef = React.useRef(null);
  React.useEffect(() => {
    const onScroll = () => {
      const max = document.documentElement.scrollHeight - window.innerHeight;
      const p = max > 0 ? (window.scrollY / max) * 100 : 0;
      if (fillRef.current) fillRef.current.style.height = p + '%';
    };
    window.addEventListener('scroll', onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener('scroll', onScroll);
  }, []);
  return (
    <div className="progress-rail">
      <div className="progress-rail-fill" ref={fillRef}></div>
    </div>
  );
}

// ──────────────────────────────────────────────────────────
// APP ROOT
// ──────────────────────────────────────────────────────────
function App() {
  const [booted, setBooted] = React.useState(false);

  // Initialize neural canvas + apply locked preset
  React.useEffect(() => {
    const cv = document.getElementById('neural-canvas');
    if (cv && !window.__neural) {
      window.__neural = new NeuralCanvas(cv);
    }
    applyAccent('cyan');
    applyTypography('cinematic');
    applyConcept('mesh');
    applyIntensity('max');
    applyTheme(false);
  }, []);

  // Initialize PinEngine + neural canvas
  React.useEffect(() => {
    if (!booted) return;
    // Wait one tick for sections to mount
    const t = setTimeout(() => {
      if (window.PinEngine && !window.__pin) {
        window.__pin = new PinEngine();
        window.__pin.init();
      }
    }, 50);
    return () => clearTimeout(t);
  }, [booted]);

  // Reveal — scroll-based check (works in sandboxed iframes where IO can stall)
  React.useEffect(() => {
    if (!booted) return;
    const check = () => {
      const vh = window.innerHeight;
      document.querySelectorAll('.reveal:not(.in)').forEach(el => {
        const r = el.getBoundingClientRect();
        if (r.top < vh - 60 && r.bottom > 0) {
          el.classList.add('in');
        }
      });
    };
    // First pass: tag everything currently in view immediately (no flash)
    requestAnimationFrame(check);
    // Also try IO for environments that support it
    let io;
    try {
      io = new IntersectionObserver((entries) => {
        entries.forEach(e => {
          if (e.isIntersecting) {
            e.target.classList.add('in');
            io.unobserve(e.target);
          }
        });
      }, { threshold: 0.08, rootMargin: '0px 0px -40px 0px' });
      document.querySelectorAll('.reveal').forEach(el => io.observe(el));
    } catch (e) { /* noop */ }

    window.addEventListener('scroll', check, { passive: true });
    window.addEventListener('resize', check);
    // Failsafe: after 600ms, anything not in view via observer gets re-checked
    const t = setTimeout(check, 600);
    return () => {
      window.removeEventListener('scroll', check);
      window.removeEventListener('resize', check);
      clearTimeout(t);
      if (io) io.disconnect();
    };
  }, [booted]);

  return (
    <React.Fragment>
      {!booted && <BootLoader onDone={() => setBooted(true)} />}
      {booted && (
        <React.Fragment>
          <CursorLight />
          <Chrome />
          <ProgressRail />
          <main>
            <Identity />
            <Infrastructure />
            <Intelligence />
            <Horizon />
            <Contact />
          </main>
        </React.Fragment>
      )}
    </React.Fragment>
  );
}

window.App = App;
