// Boot.jsx — Alien/Nostromo-style cold-boot terminal
// Dense CRT console: memcheck, self-test, handshake, roster sync, then a
// split-open reveal into the landing page.

const { useState, useEffect, useRef } = React;

// --- text banks ---------------------------------------------------------
const BOOT_LINES = [
  { t: 90,   s: ">_ OER.CORE // BIOS v2.14.7 // © ONE EARTH RISING" },
  { t: 120,  s: "MEMCHECK ......................... 16,384 K OK" },
  { t: 70,   s: "CRYPTO MODULE .................... SEC-4 OK" },
  { t: 90,   s: "HANDSHAKE // oga-net.nostromo.08 .. ESTABLISHED" },
  { t: 70,   s: "LOADING KERNEL ................... /oer/core/k.img" },
  { t: 140,  s: "MOUNTING LIBRARY ................. /mnt/legends" },
  { t: 70,   s: "ROSTER SYNC ...................... 170,482 ASSETS" },
  { t: 70,   s: "PARTNER TITLES ................... 12 / 12 ONLINE" },
  { t: 110,  s: "IDENTITY BRIDGE .................. VERIFIED" },
  { t: 70,   s: "SCANNING FOR ANOMALIES ........... NONE" },
  { t: 90,   s: "STREAM ENGINE .................... STABLE" },
  { t: 80,   s: "READY." },
];

const HEX = "0123456789ABCDEF";
const randHex = (n=8) => Array.from({length:n},()=>HEX[Math.floor(Math.random()*16)]).join("");

function useNow() {
  const [t,setT] = useState(()=>new Date());
  useEffect(()=>{ const id = setInterval(()=>setT(new Date()),1000); return ()=>clearInterval(id); },[]);
  return t;
}

// --- typewriter line ----------------------------------------------------
function TypeLine({ text, speed=8, onDone }) {
  const [n, setN] = useState(0);
  useEffect(() => {
    if (n >= text.length) { onDone && onDone(); return; }
    const id = setTimeout(()=>setN(n+1), speed);
    return ()=>clearTimeout(id);
  }, [n, text, speed]);
  return <span>{text.slice(0,n)}</span>;
}

// --- the boot screen ----------------------------------------------------
function Boot({ onDone, skippable=true }) {
  const [lines, setLines] = useState([]);     // shown lines
  const [idx, setIdx]     = useState(0);      // index into BOOT_LINES
  const [phase, setPhase] = useState("boot"); // boot | warn | title | exit
  const [bar, setBar]     = useState(0);      // progress 0..100
  const [sessionId] = useState(() => randHex(8));
  const scrollRef = useRef(null);
  const now = useNow();

  // roll boot lines
  useEffect(() => {
    if (phase !== "boot") return;
    if (idx >= BOOT_LINES.length) {
      const w = setTimeout(()=>setPhase("warn"), 240);
      return ()=>clearTimeout(w);
    }
    const { t, s } = BOOT_LINES[idx];
    const id = setTimeout(()=>{
      setLines(ls => [...ls, s]);
      setIdx(i => i+1);
      setBar(Math.round(((idx+1)/BOOT_LINES.length)*100));
      if (scrollRef.current) scrollRef.current.scrollTop = 9999;
    }, t);
    return ()=>clearTimeout(id);
  }, [idx, phase]);

  // warn flash → title reveal → exit
  useEffect(() => {
    if (phase === "warn")  { const id = setTimeout(()=>setPhase("title"), 350); return ()=>clearTimeout(id); }
    if (phase === "title") { const id = setTimeout(()=>setPhase("exit"),  4200); return ()=>clearTimeout(id); }
    if (phase === "exit")  { const id = setTimeout(()=>onDone && onDone(), 620); return ()=>clearTimeout(id); }
  }, [phase]);

  // skip on keypress / click
  useEffect(() => {
    if (!skippable) return;
    const skip = () => { if (phase !== "exit") setPhase("exit"); };
    window.addEventListener("keydown", skip);
    return ()=>window.removeEventListener("keydown", skip);
  }, [phase]);

  const exiting = phase === "exit";

  const tUTC = `${String(now.getUTCHours()).padStart(2,"0")}:${String(now.getUTCMinutes()).padStart(2,"0")}:${String(now.getUTCSeconds()).padStart(2,"0")} UTC`;

  return (
    <div style={{
      position:"fixed", inset:0, zIndex:9000, background:"#000", color:"var(--oga-neon)",
      fontFamily:"var(--oga-font-mono)", overflow:"hidden", cursor: skippable ? "pointer" : "default",
    }} onClick={() => skippable && phase !== "exit" && setPhase("exit")}>

      {/* CRT layers */}
      <div className="crt-grid"/>
      <div className="crt-scan"/>
      <div className="crt-vig"/>
      <div className="crt-noise"/>
      <div className="crt-rolling"/>

      {/* corner brackets */}
      <Bracket corner="tl"/><Bracket corner="tr"/><Bracket corner="bl"/><Bracket corner="br"/>

      {/* top status row */}
      <div style={topBar}>
        <span>WEYLAND-STANDARD CONSOLE // OER.CORE</span>
        <span style={{opacity:.7}}>SESSION 0x{sessionId}</span>
        <span>{tUTC}</span>
      </div>

      {/* split-open panels on exit */}
      <div style={{
        position:"absolute", inset:0, display:"flex", flexDirection:"column", pointerEvents:"none", zIndex:8,
      }}>
        <div style={{flex:1, background:"#000", borderBottom:"1px solid var(--oga-neon)",
          transform: exiting ? "translateY(-101%)" : "translateY(0)",
          transition:"transform 600ms cubic-bezier(.7,0,.2,1)",
          boxShadow:"0 2px 40px rgba(57,255,20,.5)"}}/>
        <div style={{flex:1, background:"#000", borderTop:"1px solid var(--oga-neon)",
          transform: exiting ? "translateY(101%)" : "translateY(0)",
          transition:"transform 600ms cubic-bezier(.7,0,.2,1)",
          boxShadow:"0 -2px 40px rgba(57,255,20,.5)"}}/>
      </div>

      {/* central console */}
      <div style={{
        position:"absolute", inset:0, display:"grid",
        gridTemplateColumns:"minmax(0,1fr) minmax(0,1fr)",
        gridTemplateRows:"auto 1fr auto",
        padding:"52px clamp(18px,5vw,80px) 44px",
        gap:"clamp(18px,3vw,40px)",
      }}>

        {/* header banner */}
        <div style={{gridColumn:"1 / -1", display:"flex", flexDirection:"column", gap:10}}>
          <div style={headerRow}>
            <span className="blinkDim">●</span>
            <span>OER/OGA PROTOCOL · NODE NOSTROMO-08</span>
            <span style={{marginLeft:"auto",opacity:.7}}>PRIORITY: ALPHA</span>
          </div>
          <pre style={asciiBanner}>{asciiOga()}</pre>
          <div style={{
            fontSize:10, letterSpacing:".28em", opacity:.65, textTransform:"uppercase",
          }}>// ownable game assets™ // one library, only legends</div>
        </div>

        {/* left column — log */}
        <div style={panel}>
          <div style={panelTitle}>
            <span>&gt;_ SYSTEM.LOG</span>
            <span style={{opacity:.6}}>[BUF 00/64K]</span>
          </div>
          <div ref={scrollRef} style={logBox}>
            {lines.map((l,i)=>{
              const ok = /OK|ESTABLISHED|VERIFIED|NONE|STABLE|ONLINE|READY/.test(l);
              const last = i === lines.length-1 && phase==="boot";
              return (
                <div key={i} style={{...logLine, opacity: i===lines.length-1 ? 1 : 0.72 }}>
                  <span style={{opacity:.4, marginRight:10}}>{String(i+1).padStart(2,"0")}</span>
                  <span>{l.replace(/OK|ESTABLISHED|VERIFIED|NONE|STABLE|ONLINE|READY/, "")}</span>
                  {ok && <span style={{color:"#0DFF00", fontWeight:700, marginLeft:4}}>
                    {(l.match(/OK|ESTABLISHED|VERIFIED|NONE|STABLE|ONLINE|READY/)||[""])[0]}
                  </span>}
                  {last && <span className="cursor">▊</span>}
                </div>
              );
            })}
            {phase !== "boot" && (
              <div style={{...logLine, color: phase==="warn" ? "var(--oga-warn)" : "var(--oga-neon)"}}>
                <span style={{opacity:.4, marginRight:10}}>{String(BOOT_LINES.length+1).padStart(2,"0")}</span>
                {phase==="warn" ? "⚠ UNAUTHORIZED VIEWERS WILL BE LOGGED." : "▸ RENDERING INTERFACE..."}
              </div>
            )}
          </div>
          {/* progress */}
          <div style={{marginTop:14}}>
            <div style={{display:"flex",justifyContent:"space-between",fontSize:10,letterSpacing:".22em",marginBottom:6,opacity:.8}}>
              <span>LOAD</span><span>{String(bar).padStart(3,"0")}%</span>
            </div>
            <div style={progOuter}>
              <div style={{...progInner, width: `${bar}%`}}/>
              <div style={progTicks}/>
            </div>
          </div>
        </div>

        {/* right column — telemetry */}
        <div style={panel}>
          <div style={panelTitle}>
            <span>&gt;_ TELEMETRY</span>
            <span className="blinkDim" style={{color:"var(--oga-neon)"}}>◉ LIVE</span>
          </div>

          <Readout label="NODE" val="NOSTROMO-08"/>
          <Readout label="UPLINK" val={<Pulse ok>99.98%</Pulse>}/>
          <Readout label="ROSTER" val={<Counter to={170482} duration={1800}/>}/>
          <Readout label="PARTNERS" val="12 / 12"/>
          <Readout label="ENTROPY" val={<EntropyTape/>}/>

          {/* isometric signal chart */}
          <div style={{marginTop:14}}>
            <div style={{fontSize:10, letterSpacing:".22em", opacity:.65, marginBottom:8}}>SIGNAL &gt; PORTAL_PASS</div>
            <WaveCanvas/>
          </div>

          <div style={{marginTop:14, fontSize:11, opacity:.8, lineHeight:1.6}}>
            <div>▸ IDENTITY PRESERVED ACROSS <b style={{color:"#F2F2F2"}}>ALL</b> PARTNERED TITLES.</div>
            <div>▸ LOADOUT · BACKSTORY · PROGRESSION = ONE CHARACTER.</div>
          </div>
        </div>

        {/* footer — call to enter */}
        <div style={{gridColumn:"1 / -1", display:"flex",justifyContent:"space-between",alignItems:"flex-end",gap:24}}>
          <div style={{fontSize:10, letterSpacing:".22em",opacity:.7}}>
            SYSTEM STATUS: OPERATIONAL &nbsp;//&nbsp; DATA FLOW: STABLE &nbsp;//&nbsp; <span className="blinkDim">CARRIER LOCKED</span>
          </div>

          {phase !== "boot" && (
            <div style={{
              display:"flex", alignItems:"center", gap:14, opacity: exiting ? 0 : 1,
              transition:"opacity 200ms",
            }}>
              <span style={{fontSize:10,letterSpacing:".24em",opacity:.7}}>&gt;_ PRESS ANY KEY TO ENTER</span>
              <button onClick={(e)=>{e.stopPropagation(); setPhase("exit");}} style={enterBtn}>
                ▸ ENTER_LIBRARY
              </button>
            </div>
          )}
        </div>
      </div>

      {/* giant title overlay during 'title' phase */}
      {phase !== "boot" && (
        <div style={{
          position:"absolute", inset:0, display:"grid", placeItems:"center",
          zIndex:9, pointerEvents:"none",
          opacity: phase === "title" ? 1 : 0,
          transition:"opacity 300ms ease",
        }}>
          <div style={{textAlign:"center"}}>
            <div style={{fontSize:11, letterSpacing:".32em", opacity:.75, marginBottom:18}}>
              &gt;_ WELCOME, OPERATOR
            </div>
            <div style={{
              fontFamily:"var(--oga-font-display)", fontWeight:900,
              fontSize:"clamp(64px,11vw,148px)", lineHeight:.88, letterSpacing:"-0.035em",
              textTransform:"uppercase", color:"#F2F2F2",
            }}>
              ONE LIBRARY,<br/>
              <span style={{color:"var(--oga-neon)", textShadow:"0 0 40px rgba(57,255,20,.55)"}}>ONLY LEGENDS.</span>
            </div>
          </div>
        </div>
      )}

      <style>{bootCSS}</style>
    </div>
  );
}

// -------- sub-primitives ------------------------------------------------
function Bracket({corner}) {
  const base = { position:"absolute", width:28, height:28, zIndex:20, pointerEvents:"none" };
  const map = {
    tl:{top:16,left:16, borderTop:"1px solid var(--oga-neon)", borderLeft:"1px solid var(--oga-neon)"},
    tr:{top:16,right:16,borderTop:"1px solid var(--oga-neon)", borderRight:"1px solid var(--oga-neon)"},
    bl:{bottom:16,left:16,borderBottom:"1px solid var(--oga-neon)", borderLeft:"1px solid var(--oga-neon)"},
    br:{bottom:16,right:16,borderBottom:"1px solid var(--oga-neon)", borderRight:"1px solid var(--oga-neon)"},
  };
  return <div style={{...base, ...map[corner], boxShadow:"0 0 12px rgba(57,255,20,.25)"}}/>;
}

function Readout({label, val}) {
  return (
    <div style={{
      display:"flex",alignItems:"center",gap:12,padding:"8px 0",
      borderBottom:"1px dashed rgba(57,255,20,.18)",fontSize:12,
    }}>
      <span style={{opacity:.6,letterSpacing:".2em",minWidth:96, textTransform:"uppercase"}}>{label}</span>
      <span style={{flex:1, letterSpacing:".08em"}}>
        {".".repeat(14)}
      </span>
      <span style={{fontWeight:700, color:"#F2F2F2"}}>{val}</span>
    </div>
  );
}

function Counter({to, duration=1400}) {
  const [n, setN] = useState(0);
  useEffect(()=>{
    const start = performance.now();
    let raf;
    const tick = (t)=>{
      const k = Math.min(1, (t-start)/duration);
      const eased = 1 - Math.pow(1-k, 3);
      setN(Math.floor(eased*to));
      if (k<1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return ()=>cancelAnimationFrame(raf);
  },[to,duration]);
  return <span style={{color:"var(--oga-neon)"}}>{n.toLocaleString()}</span>;
}

function Pulse({children, ok}) {
  return <span style={{color: ok ? "var(--oga-neon)" : "var(--oga-warn)"}} className="pulseGlow">{children}</span>;
}

function EntropyTape() {
  const [s, setS] = useState(randHex(10));
  useEffect(()=>{ const id = setInterval(()=>setS(randHex(10)), 110); return ()=>clearInterval(id);},[]);
  return <span style={{letterSpacing:".18em", color:"var(--oga-neon)"}}>{s}</span>;
}

function WaveCanvas() {
  const ref = useRef(null);
  useEffect(() => {
    const c = ref.current; if (!c) return;
    const ctx = c.getContext("2d");
    const DPR = Math.min(devicePixelRatio||1, 2);
    let raf, stopped=false;
    const resize = () => {
      const r = c.getBoundingClientRect();
      c.width = r.width*DPR; c.height = r.height*DPR;
    };
    resize();
    window.addEventListener("resize", resize);

    const start = performance.now();
    const loop = (t) => {
      if (stopped) return;
      const w = c.width, h = c.height, tt = (t-start)/1000;
      ctx.clearRect(0,0,w,h);
      // horizon line
      ctx.strokeStyle = "rgba(57,255,20,.18)";
      ctx.lineWidth = 1*DPR;
      ctx.beginPath(); ctx.moveTo(0, h*0.5); ctx.lineTo(w, h*0.5); ctx.stroke();

      // 3 layered waves
      for (let k=0;k<3;k++) {
        ctx.beginPath();
        for (let x=0;x<=w;x+=2) {
          const f = (x/w)*6 + tt*(0.6 + k*0.4);
          const amp = (h*0.28) * (1 - k*0.28);
          const y = h*0.5 + Math.sin(f)*amp*0.6 + Math.sin(f*2.3+k)*amp*0.4;
          if (x===0) ctx.moveTo(x,y); else ctx.lineTo(x,y);
        }
        ctx.strokeStyle = `rgba(57,255,20,${0.75 - k*0.22})`;
        ctx.lineWidth = (1.4 - k*0.3)*DPR;
        ctx.shadowColor = "rgba(57,255,20,.8)";
        ctx.shadowBlur = 6*DPR*(1-k*0.3);
        ctx.stroke();
      }
      raf = requestAnimationFrame(loop);
    };
    raf = requestAnimationFrame(loop);
    return () => { stopped=true; cancelAnimationFrame(raf); window.removeEventListener("resize", resize); };
  }, []);
  return <canvas ref={ref} style={{width:"100%", height:80, display:"block", border:"1px solid rgba(57,255,20,.2)"}}/>;
}

// ascii logo banner
function asciiOga() {
  return [
"  ██████╗  ██████╗  █████╗   ██╗  ██╗██╗   ██╗██████╗ ",
" ██╔═══██╗██╔════╝ ██╔══██╗  ██║  ██║██║   ██║██╔══██╗",
" ██║   ██║██║  ███╗███████║  ███████║██║   ██║██████╔╝",
" ██║   ██║██║   ██║██╔══██║  ██╔══██║██║   ██║██╔══██╗",
" ╚██████╔╝╚██████╔╝██║  ██║  ██║  ██║╚██████╔╝██████╔╝",
"  ╚═════╝  ╚═════╝ ╚═╝  ╚═╝  ╚═╝  ╚═╝ ╚═════╝ ╚═════╝ ",
  ].join("\n");
}

// ---- styles / css ------------------------------------------------------
const topBar = {
  position:"absolute", top:0,left:0,right:0, height:30, zIndex:12,
  display:"flex", alignItems:"center", justifyContent:"space-between",
  padding:"0 24px", fontSize:10, letterSpacing:".24em", textTransform:"uppercase",
  color:"var(--oga-neon)", borderBottom:"1px solid rgba(57,255,20,.25)",
  background:"rgba(0,0,0,.65)", backdropFilter:"blur(4px)",
};
const headerRow = {
  display:"flex", alignItems:"center", gap:12, fontSize:11, letterSpacing:".24em",
  color:"var(--oga-neon)",
};
const asciiBanner = {
  margin:0, fontFamily:"var(--oga-font-mono)", fontSize:"clamp(6px,1vw,12px)",
  lineHeight:1, color:"var(--oga-neon)", textShadow:"0 0 10px rgba(57,255,20,.5)",
  whiteSpace:"pre",
};
const panel = {
  border:"1px solid rgba(57,255,20,.35)",
  boxShadow:"0 0 14px rgba(57,255,20,.18), inset 0 0 18px rgba(57,255,20,.06)",
  padding:"18px 20px", background:"rgba(0,0,0,.4)", position:"relative",
  display:"flex", flexDirection:"column", minHeight:0,
};
const panelTitle = {
  display:"flex", justifyContent:"space-between", alignItems:"center",
  fontSize:11, letterSpacing:".24em", textTransform:"uppercase",
  paddingBottom:10, marginBottom:10, borderBottom:"1px solid rgba(57,255,20,.25)",
};
const logBox = {
  flex:1, minHeight:220, overflow:"hidden", fontSize:12, lineHeight:1.65,
  paddingRight:6,
};
const logLine = { whiteSpace:"pre", fontVariantNumeric:"tabular-nums" };
const progOuter = { position:"relative", height:8, border:"1px solid rgba(57,255,20,.35)", background:"rgba(57,255,20,.06)" };
const progInner = { position:"absolute", top:0,left:0,bottom:0, background:"var(--oga-neon)", boxShadow:"0 0 10px var(--oga-neon)", transition:"width 140ms linear" };
const progTicks = { position:"absolute", inset:0, backgroundImage:"repeating-linear-gradient(90deg, transparent 0 11px, rgba(0,0,0,.5) 11px 12px)" };
const enterBtn = {
  appearance:"none", border:"1px solid var(--oga-neon)", background:"rgba(57,255,20,.12)",
  color:"var(--oga-neon)", padding:"12px 22px", fontFamily:"var(--oga-font-mono)",
  fontWeight:700, letterSpacing:".22em", textTransform:"uppercase", fontSize:12,
  cursor:"pointer", boxShadow:"0 0 16px rgba(57,255,20,.35)",
};

const bootCSS = `
@keyframes blink { 50% { opacity: 0 } }
.cursor { display:inline-block; margin-left:4px; animation: blink 1s steps(2) infinite; }
.blinkDim { animation: blink 1.4s steps(2) infinite; }
.pulseGlow { text-shadow: 0 0 10px currentColor; }

.crt-grid {
  position:absolute; inset:0; pointer-events:none; z-index:1;
  background:
    linear-gradient(rgb(57 255 20 / 0.06) 1px, transparent 1px) 0 0 / 40px 40px,
    linear-gradient(90deg, rgb(57 255 20 / 0.06) 1px, transparent 1px) 0 0 / 40px 40px;
  mask-image: radial-gradient(ellipse at 50% 55%, #000 30%, rgba(0,0,0,.35) 70%, transparent 100%);
  animation: gridDrift 18s linear infinite;
}
@keyframes gridDrift { to { background-position: 40px 40px, 40px 40px; } }

.crt-scan {
  position:absolute; inset:0; pointer-events:none; z-index:2;
  background: repeating-linear-gradient(0deg,
    rgba(57,255,20,.05) 0px, rgba(57,255,20,.05) 1px,
    transparent 1px, transparent 3px);
  mix-blend-mode: screen;
}
.crt-rolling {
  position:absolute; inset:-20% 0; pointer-events:none; z-index:3;
  background: linear-gradient(180deg, transparent 0%, rgba(57,255,20,.08) 48%, rgba(57,255,20,.16) 50%, rgba(57,255,20,.08) 52%, transparent 100%);
  animation: roll 7s linear infinite;
  mix-blend-mode: screen;
}
@keyframes roll { 0% { transform: translateY(-60%); } 100% { transform: translateY(60%); } }

.crt-vig {
  position:absolute; inset:0; pointer-events:none; z-index:4;
  background: radial-gradient(ellipse at center, transparent 50%, rgba(0,0,0,.7) 100%);
}
.crt-noise {
  position:absolute; inset:0; pointer-events:none; z-index:5;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.22  0 0 0 0 1  0 0 0 0 0.08  0 0 0 0.5 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)' opacity='0.35'/></svg>");
  opacity:.25; mix-blend-mode: screen;
  animation: nshift 1.2s steps(6) infinite;
}
@keyframes nshift { to { background-position: 160px 0; } }
`;

Object.assign(window, { Boot });
