// Boot-up loading screen — terminal init sequence with per-character typing
const { useState, useEffect, useRef } = React;

function LoadingScreen({ onSettling, onDone }) {
  const [phase, setPhase] = useState("typing"); // typing → fading
  const [committed, setCommitted] = useState([]); // fully-typed past lines
  const [active, setActive] = useState(null);     // { kind, text, typed }
  const [progress, setProgress] = useState(0);
  const brandRef = useRef(null);

  const sequence = [
    { kind: "info",  text: "booting nyxoril.dev v1.0.0",            postDelay: 140 },
    { kind: "ok",    text: "renderer ready · gpu accelerated",      postDelay: 120 },
    { kind: "load",  text: "loading assets/pfp.png",                postDelay: 180 },
    { kind: "load",  text: "compiling shaders…",                    postDelay: 240 },
    { kind: "ok",    text: "shaders compiled · 6 covers ready",     postDelay: 120 },
    { kind: "load",  text: "mounting <Portfolio />",                postDelay: 160 },
    { kind: "info",  text: "engines online: Unreal · Unity · Godot · Web", postDelay: 200 },
    { kind: "ok",    text: "ready · welcome",                       postDelay: 250 }
  ];

  // when phase flips to fading, morph the brand mark to the hero avatar
  useEffect(() => {
    if (phase !== "fading") return;
    onSettling && onSettling();
    const morphTo = () => {
      const target = document.querySelector(".hero__avatar");
      const brand = brandRef.current;
      if (!target || !brand) return;
      const t = target.getBoundingClientRect();
      const b = brand.getBoundingClientRect();
      const dx = (t.left + t.width / 2) - (b.left + b.width / 2);
      const dy = (t.top + t.height / 2) - (b.top + b.height / 2);
      const scale = t.width / b.width;
      brand.style.setProperty("--morph-x", `${dx}px`);
      brand.style.setProperty("--morph-y", `${dy}px`);
      brand.style.setProperty("--morph-scale", String(scale));
    };
    requestAnimationFrame(() => requestAnimationFrame(morphTo));
  }, [phase, onSettling]);

  useEffect(() => {
    if (sessionStorage.getItem("nyx_seen_boot")) {
      onDone();
      return;
    }

    let timer;
    let cancelled = false;
    let targetProgress = 0;
    let progRaf;

    // smooth progress tweener — eases the bar toward targetProgress every frame
    let displayed = 0;
    const tween = () => {
      if (cancelled) return;
      displayed += (targetProgress - displayed) * 0.18;
      if (Math.abs(targetProgress - displayed) < 0.2 && targetProgress >= 100) displayed = 100;
      setProgress(displayed);
      progRaf = requestAnimationFrame(tween);
    };
    progRaf = requestAnimationFrame(tween);

    const finish = () => {
      if (cancelled) return;
      targetProgress = 100;
      setActive(null);
      timer = setTimeout(() => {
        if (cancelled) return;
        setPhase("fading");
        timer = setTimeout(() => {
          if (cancelled) return;
          sessionStorage.setItem("nyx_seen_boot", "1");
          onDone();
        }, 1100);
      }, 280);
    };

    let li = 0;
    // type one character of the current line at a time, then commit & advance
    const typeNext = () => {
      if (cancelled) return;
      if (li >= sequence.length) { finish(); return; }
      const step = sequence[li];
      const chars = step.text.length;
      let ci = 0;
      // set initial active line (tag visible, empty text)
      setActive({ kind: step.kind, text: step.text, typed: "" });
      const charDelay = Math.max(9, 22 - chars * 0.18); // shorter for longer lines
      const typeChar = () => {
        if (cancelled) return;
        ci++;
        setActive({ kind: step.kind, text: step.text, typed: step.text.slice(0, ci) });
        if (ci < chars) {
          timer = setTimeout(typeChar, charDelay + (Math.random() < 0.08 ? 30 : 0));
        } else {
          // commit, bump progress, schedule next
          setCommitted((c) => [...c, step]);
          setActive(null);
          li++;
          targetProgress = Math.round((li / sequence.length) * 100);
          timer = setTimeout(typeNext, step.postDelay);
        }
      };
      timer = setTimeout(typeChar, 60);
    };

    timer = setTimeout(typeNext, 260);

    const skip = () => {
      if (cancelled) return;
      sessionStorage.setItem("nyx_seen_boot", "1");
      cancelled = true;
      clearTimeout(timer);
      cancelAnimationFrame(progRaf);
      setPhase("fading");
      setTimeout(onDone, 900);
    };
    window.addEventListener("keydown", skip);
    window.addEventListener("click", skip);
    return () => {
      cancelled = true;
      clearTimeout(timer);
      cancelAnimationFrame(progRaf);
      window.removeEventListener("keydown", skip);
      window.removeEventListener("click", skip);
    };
    // eslint-disable-next-line
  }, []);

  const tagColor = {
    info: "oklch(0.85 0.18 195)",
    ok:   "oklch(0.85 0.18 145)",
    load: "oklch(0.85 0.18 50)",
    err:  "oklch(0.85 0.18 25)"
  };
  const tagLabel = { info: "INFO", ok: "OK  ", load: "LOAD", err: "ERR " };

  return (
    <div className={`boot ${phase === "fading" ? "boot--fading" : ""}`}>
      <div className="boot__grid" />
      <div className="boot__scan" />

      <div className="boot__brand">
        <div className="boot__brand-mark" ref={brandRef}>
          <img src="assets/pfp.png" alt="" />
          <div className="boot__brand-ring" />
          <div className="boot__brand-ring boot__brand-ring--2" />
        </div>
        <div className="boot__brand-text">
          <div className="boot__brand-name mono">NYXORIL.DEV</div>
          <div className="boot__brand-sub mono">cédrick picard · game developer</div>
        </div>
      </div>

      <div className="boot__term">
        <div className="boot__term-head mono">
          <span className="boot__term-lights">
            <span /><span /><span />
          </span>
          <span>~ ❯ ./start.sh</span>
        </div>
        <div className="boot__term-body mono">
          {committed.filter(Boolean).map((l, i) => (
            <div key={i} className="boot__line">
              <span className="boot__tag" style={{ color: tagColor[l.kind] }}>[{tagLabel[l.kind]}]</span>
              <span className="boot__line-text">{l.text}</span>
            </div>
          ))}
          {active && (
            <div className="boot__line boot__line--active">
              <span className="boot__tag" style={{ color: tagColor[active.kind] }}>[{tagLabel[active.kind]}]</span>
              <span className="boot__line-text">
                {active.typed}
                <span className="boot__caret">▮</span>
              </span>
            </div>
          )}
          {!active && phase === "typing" && (
            <div className="boot__line boot__line--idle">
              <span className="boot__caret">▮</span>
            </div>
          )}
        </div>
      </div>

      <div className="boot__progress">
        <div className="boot__progress-track">
          <div className="boot__progress-fill" style={{ width: `${progress}%` }} />
          <div className="boot__progress-glow" style={{ left: `${progress}%` }} />
        </div>
        <div className="boot__progress-meta mono">
          <span className="boot__progress-pct">{String(Math.round(progress)).padStart(3, "0")}%</span>
          <span className="boot__progress-hint">click anywhere to skip</span>
        </div>
      </div>
    </div>
  );
}

window.LoadingScreen = LoadingScreen;
