// ===== Hooks & helpers =====
const { useState, useEffect, useRef } = React;

const PARTICLE_PALETTE = ["#22d3ee", "#a78bfa"];

function useTypewriter(lines, { charDelay = 28, holdMs = 1700, lineGap = 350 } = {}) {
  const [lineIdx, setLineIdx] = useState(0);
  const [text, setText] = useState("");
  const [phase, setPhase] = useState("typing"); // typing | holding | erasing
  const [history, setHistory] = useState([]);

  useEffect(() => {
    let t;
    const current = lines[lineIdx];
    if (phase === "typing") {
      if (text.length < current.length) {
        t = setTimeout(() => setText(current.slice(0, text.length + 1)), charDelay);
      } else {
        t = setTimeout(() => setPhase("holding"), 80);
      }
    } else if (phase === "holding") {
      t = setTimeout(() => setPhase("erasing"), holdMs);
    } else if (phase === "erasing") {
      // commit once, then advance — guard with text length so we only fire on entry
      if (text !== "") {
        setHistory((h) => [...h, current].slice(-3));
        setText("");
      } else {
        t = setTimeout(() => {
          setLineIdx((i) => (i + 1) % lines.length);
          setPhase("typing");
        }, lineGap);
      }
    }
    return () => clearTimeout(t);
  }, [text, phase, lineIdx, lines, charDelay, holdMs, lineGap]);

  return { text, history };
}

// ===== Particles (canvas) =====
function Particles({ density = 0.00009, palette = PARTICLE_PALETTE, glow = true }) {
  const ref = useRef(null);
  useEffect(() => {
    const canvas = ref.current;
    const ctx = canvas.getContext("2d");
    let raf, w, h, parts;
    const dpr = Math.min(window.devicePixelRatio || 1, 2);

    const resize = () => {
      const rect = canvas.parentElement.getBoundingClientRect();
      w = rect.width; h = rect.height;
      canvas.width = w * dpr; canvas.height = h * dpr;
      canvas.style.width = w + "px"; canvas.style.height = h + "px";
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
      const count = Math.max(28, Math.floor(w * h * density));
      parts = Array.from({ length: count }).map(() => ({
        x: Math.random() * w,
        y: Math.random() * h,
        r: Math.random() * 1.4 + 0.4,
        vx: (Math.random() - 0.5) * 0.12,
        vy: (Math.random() - 0.5) * 0.12 - 0.04,
        c: palette[Math.floor(Math.random() * palette.length)],
        a: Math.random() * 0.6 + 0.2,
        ph: Math.random() * Math.PI * 2,
      }));
    };

    const tick = (t) => {
      ctx.clearRect(0, 0, w, h);
      for (const p of parts) {
        p.x += p.vx; p.y += p.vy;
        if (p.x < -8) p.x = w + 8;
        if (p.x > w + 8) p.x = -8;
        if (p.y < -8) p.y = h + 8;
        if (p.y > h + 8) p.y = -8;
        const flicker = 0.65 + 0.35 * Math.sin(t * 0.001 + p.ph);
        ctx.beginPath();
        ctx.fillStyle = p.c;
        ctx.globalAlpha = p.a * flicker;
        if (glow) ctx.shadowBlur = 8; else ctx.shadowBlur = 0;
        ctx.shadowColor = p.c;
        ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2);
        ctx.fill();
      }
      ctx.globalAlpha = 1;
      raf = requestAnimationFrame(tick);
    };

    resize();
    raf = requestAnimationFrame(tick);
    const ro = new ResizeObserver(resize);
    ro.observe(canvas.parentElement);
    return () => { cancelAnimationFrame(raf); ro.disconnect(); };
  }, [density, palette, glow]);
  return <canvas ref={ref} style={{ width: "100%", height: "100%", display: "block" }} />;
}

// ===== Hero overlays =====
const PULSE_NODES = [
  { x: 32, y: 32, c: "cyan",   d: 0,   s: 1   },
  { x: 50, y: 22, c: "cyan",   d: 0.6, s: 1.1 },
  { x: 67, y: 30, c: "violet", d: 1.2, s: 0.9 },
  { x: 38, y: 48, c: "cyan",   d: 0.4, s: 0.7 },
  { x: 60, y: 46, c: "cyan",   d: 1.6, s: 0.8 },
  { x: 28, y: 62, c: "violet", d: 0.9, s: 0.85 },
  { x: 72, y: 60, c: "cyan",   d: 1.3, s: 0.95 },
  { x: 18, y: 42, c: "violet", d: 1.8, s: 0.75 },
  { x: 82, y: 40, c: "cyan",   d: 0.2, s: 0.7 },
];

function PulseNodes() {
  return (
    <div className="hero__pulses" aria-hidden="true">
      {PULSE_NODES.map((n, i) => (
        <span
          key={i}
          className={`pulse-node ${n.c === "violet" ? "violet" : ""} ${n.s < 0.85 ? "small" : ""}`}
          style={{
            left: `${n.x}%`,
            top: `${n.y}%`,
            animationDelay: `${n.d}s`,
            transform: `scale(${n.s})`,
          }}
        />
      ))}
    </div>
  );
}

function Sparks() {
  const sparks = [
    { x: 56, y: 58, d: 0 },
    { x: 58, y: 56, d: 1.1 },
    { x: 54, y: 60, d: 2.3 },
    { x: 57, y: 54, d: 3.0 },
  ];
  return (
    <div className="hero__sparks" aria-hidden="true">
      {sparks.map((s, i) => (
        <span
          key={i}
          className="spark"
          style={{ left: `${s.x}%`, top: `${s.y}%`, animationDelay: `${s.d}s` }}
        />
      ))}
    </div>
  );
}

// ===== Hero (single page, build language) =====
const TERMINAL_LINES = [
  "pip install --upgrade portfolio",
  "await agents.build_page()",
  "loading prompt templates",
  "running pytest -k test_personality",
  "uvicorn main:app --reload",
  "git commit -m 'wip: more sparks'",
];

function Hero() {
  const { Cpu } = window.Icons;
  const { text, history } = useTypewriter(TERMINAL_LINES);

  // agentic "live" metrics
  const [tokens, setTokens] = useState(86.4);
  useEffect(() => {
    const id = setInterval(() => {
      setTokens(+(30 + Math.random() * 120).toFixed(1));
    }, 1300);
    return () => clearInterval(id);
  }, []);
  const progress = 63;

  return (
    <section className="hero" aria-label="Hero">
      <div className="hero__bg" />
      <div className="hero__overlay" />
      <div className="hero__grain" />
      <PulseNodes />
      <Sparks />
      <div className="hero__particles">
        <Particles density={0.00007} />
      </div>

      <div className="hero__inner">
        <header className="topbar">
          <div className="brand">
            <span className="brand__mark"><Cpu size={14} /></span>
            <span className="brand__name">Kacper Borowiecki</span>
            <span className="brand__sep">·</span>
            <span>AI Automation Lead</span>
          </div>
          <div className="statuspill">
            <span className="statuspill__dot" aria-hidden="true" />
            <span>Build in progress</span>
          </div>
        </header>

        <div className="hero__center">
          <span className="tag">
            <span className="tag__beam" />
            // SYSTEM STATUS: BUILDING
            <span className="tag__beam" style={{ transform: "scaleX(-1)" }} />
          </span>
          <h1 className="headline">
            Site under construction<span className="headline__caret" aria-hidden="true" />
          </h1>
          <p className="subhead">
            A few small robots are welding this page together right now. Please stand clear of the sparks.{" "}
            <em>Build&nbsp;0.1.0-alpha</em>
          </p>

          <div className="terminal" aria-hidden="true">
            <div className="terminal__head">
              <span className="terminal__sessionlamp" />
              <span className="terminal__sessiontag">ubuntu</span>
              <span className="terminal__path">kacper@homelab:~$</span>
              <span className="terminal__pid">venv · py3.12</span>
            </div>
            <div className="terminal__body">
              <div className="terminal__hist">
                {history.map((h, i) => (
                  <div key={i} className="terminal__line" style={{ opacity: 0.35 + i * 0.15 }}>
                    <span className="terminal__prompt">›</span>
                    <span className="terminal__hist-text">{h}</span>
                    <span className="ok">ok</span>
                  </div>
                ))}
              </div>
              <div className="terminal__line">
                <span className="terminal__prompt">›</span>
                <span className="terminal__text">{text}</span>
                <span className="terminal__cursor" />
              </div>
            </div>
          </div>
        </div>
      </div>

      <aside className="metrics" aria-label="Build metrics">
        <div className="metrics__head">
          <span>build.metrics</span>
          <em>live</em>
        </div>
        <div className="metrics__row">
          <span className="metrics__label">AGENTS</span>
          <span className="metrics__val">4</span>
        </div>
        <div className="metrics__row">
          <span className="metrics__label">TOK/S</span>
          <span className="metrics__val">{tokens.toFixed(1)}<span className="up" aria-hidden="true">↑</span></span>
        </div>
        <div className="metrics__row">
          <span className="metrics__label">TASKS</span>
          <span className="metrics__val">287 done</span>
        </div>
        <div className="metrics__row">
          <span className="metrics__label">UPTIME</span>
          <span className="metrics__val">∞ days</span>
        </div>
        <div className="metrics__bar"><span style={{ width: `${progress}%` }} /></div>
      </aside>
    </section>
  );
}

// ===== Footer =====
function Footer() {
  return (
    <footer className="footer">
      <span className="footer__copy">
        <span className="footer__name">© 2026 Kacper Borowiecki</span>
        <span className="footer__sep" aria-hidden="true"> · </span>
        <span className="footer__attr">Powered by Claude, Gemini &amp; local LLMs</span>
      </span>
      <span className="footer__right">
        <span>v0.1.0-alpha</span>
        <span className="footer__caret" aria-hidden="true" />
      </span>
    </footer>
  );
}

// ===== App =====
function App() {
  return (
    <main className="page">
      <Hero />
      <Footer />
    </main>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
