/* global React, PORTFOLIO */
// Engineering-coded intro / loading screen.
// Boot readout: BD monogram, coords, version, timestamp, progress, then CTA.

const { useEffect, useRef, useState } = React;

// ── ScrambleText ────────────────────────────────────────────
// Each non-space character starts as a random ASCII glyph and
// cycles every ~50ms, locking into its final letter on a staggered
// timeline. Reads like the name is coding itself in.
const SCRAMBLE_GLYPHS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789#@$%&*+=<>/\\|{}[]";
function ScrambleText({ text, delay = 0, perChar = 70, lockDuration = 600, className }) {
  const [out, setOut] = useState(() => text.split("").map((c) => (c === " " ? " " : "·")));
  const lockedRef = useRef(new Set());

  useEffect(() => {
    let raf = 0;
    const startedAt = performance.now() + delay;
    const targets = text.split("");
    const lockAt = targets.map((c, i) => (c === " " ? 0 : delay + i * perChar + lockDuration));

    const tick = (now) => {
      const elapsed = now - (startedAt - delay);
      const next = targets.map((c, i) => {
        if (c === " ") return " ";
        if (elapsed >= lockAt[i]) {
          lockedRef.current.add(i);
          return c;
        }
        if (elapsed < delay) return "·";
        // not locked yet — pick a random glyph
        const g = SCRAMBLE_GLYPHS[Math.floor(Math.random() * SCRAMBLE_GLYPHS.length)];
        return g;
      });
      setOut(next);
      if (lockedRef.current.size < targets.filter((c) => c !== " ").length) {
        raf = requestAnimationFrame(tick);
      }
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [text, delay, perChar, lockDuration]);

  return (
    <span className={className} aria-label={text}>
      {out.map((c, i) => {
        const locked = lockedRef.current.has(i) || c === " ";
        return (
          <span
            key={i}
            aria-hidden="true"
            style={{
              display: "inline-block",
              opacity: locked ? 1 : 0.55,
              color: locked ? undefined : "var(--fg-3)",
              transition: "opacity 120ms linear, color 120ms linear",
              fontVariantNumeric: "tabular-nums",
            }}
          >
            {c === " " ? "\u00A0" : c}
          </span>
        );
      })}
    </span>
  );
}

function Intro({ onEnter }) {
  const [pct, setPct] = useState(0);
  const [now, setNow] = useState(() => new Date());
  const [ready, setReady] = useState(false);
  const [leaving, setLeaving] = useState(false);
  const startedAt = useRef(Date.now());

  // animate the progress count up to 100 over ~2.4s, matching the bar
  useEffect(() => {
    let raf = 0;
    const dur = 2400;
    const tick = () => {
      const t = Math.min(1, (Date.now() - startedAt.current) / dur);
      // ease-out
      const eased = 1 - Math.pow(1 - t, 3);
      setPct(Math.round(eased * 100));
      if (t < 1) raf = requestAnimationFrame(tick);
      else setReady(true);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, []);

  useEffect(() => {
    const t = setInterval(() => setNow(new Date()), 250);
    return () => clearInterval(t);
  }, []);

  const enter = () => {
    if (!ready || leaving) return;
    setLeaving(true);
    setTimeout(() => onEnter?.(), 580);
  };

  // Enter key support once ready
  useEffect(() => {
    const onKey = (e) => {
      if ((e.key === "Enter" || e.key === " ") && ready) {
        e.preventDefault();
        enter();
      }
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [ready, leaving]);

  const ts = fmtTimestamp(now);

  return (
    <div className={`intro ${leaving ? "intro-out" : ""}`} role="status" aria-live="polite">
      <AsciiBackground
        opacity={0.32}
        cell={9}
        scale={0.07}
        drift={0.08}
        bias={0.50}
        contrast={1.5}
      />
      <div className="intro-grid" />
      <div className="intro-corner-tl" />
      <div className="intro-corner-tr" />
      <div className="intro-corner-bl" />
      <div className="intro-corner-br" />

      <div className="intro-top">
        <div className="row gap-4" style={{ alignItems: "flex-start" }}>
          <span className="intro-mark">BD</span>
          <div className="col" style={{ gap: 4 }}>
            <span><b>Benjamin Dison</b></span>
            <span>Mechanical Engineering · Portfolio v2.0</span>
          </div>
        </div>
        <div className="col" style={{ gap: 4, textAlign: "right", alignItems: "flex-end" }}>
          <span>{PORTFOLIO.meta.coords}</span>
          <span>{PORTFOLIO.meta.location}</span>
        </div>
      </div>

      <div className="intro-center">
        <div>
          <h1 className="intro-name" aria-label="Benjamin Dison">
            <ScrambleText text="Benjamin" delay={120} perChar={85} lockDuration={520} />
            {" "}
            <ScrambleText text="Dison" delay={120 + 8 * 85} perChar={95} lockDuration={520} className="accent" />
            <span className="intro-caret" aria-hidden="true">▍</span>
          </h1>
          <div className="intro-sub">
            Engineering Portfolio · Index{" "}
            <span className="tabular">{String(PORTFOLIO.projects.length).padStart(2, "0")}</span>{" "}
            · {PORTFOLIO.meta.classOf}
          </div>
        </div>
      </div>

      <div className="intro-bottom">
        <div className="intro-readout">
          <span><b>SYS</b> · BOOT · OK</span>
          <span>SESSION · {ts.session}</span>
          <span>UTC · {ts.utc}</span>
        </div>

        <div className="intro-progress">
          <div className="intro-progress-bar">
            <div className="intro-progress-fill" />
          </div>
          <div className="intro-progress-num tabular">
            {String(pct).padStart(3, "0")} / 100 · LOADING ASSETS
          </div>
          <div className={`intro-cta ${ready ? "is-ready" : ""}`}>
            <button onClick={enter} aria-disabled={!ready}>
              Enter Portfolio <span aria-hidden="true">→</span>
            </button>
          </div>
        </div>

        <div className="intro-readout right">
          <span><b>BUILD</b> · 2026.05 — STABLE</span>
          <span>NODES · {PORTFOLIO.projects.length} PROJECTS</span>
          <span>STATUS · READY FOR INTAKE</span>
        </div>
      </div>
    </div>
  );
}

function fmtTimestamp(d) {
  const pad = (n) => String(n).padStart(2, "0");
  const utc = `${d.getUTCFullYear()}-${pad(d.getUTCMonth() + 1)}-${pad(d.getUTCDate())} ${pad(d.getUTCHours())}:${pad(d.getUTCMinutes())}:${pad(d.getUTCSeconds())}Z`;
  const sess = `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
  return { utc, session: sess };
}

Object.assign(window, { Intro });
