const { useState, useEffect, useRef, useMemo, createContext, useContext } = React;

// Shared app context for API key + provider, propagated via React context (no localStorage).
const APIContext = createContext(null);
const useAPI = () => useContext(APIContext);

// Reveal-on-scroll
function Reveal({ children, className = "", delay = 0 }) {
  const ref = useRef(null);
  useEffect(() => {
    const el = ref.current; if (!el) return;
    const io = new IntersectionObserver(([e]) => {
      if (e.isIntersecting) { setTimeout(() => el.classList.add("in"), delay); io.disconnect(); }
    }, { threshold: 0.12 });
    io.observe(el);
    return () => io.disconnect();
  }, [delay]);
  return <div ref={ref} className={`reveal ${className}`}>{children}</div>;
}

function SectionHeader({ num, kicker, title, lede, id }) {
  return (
    <div id={id} className="mb-10 sm:mb-14">
      <div className="flex items-baseline gap-4 mb-4">
        <span className="section-num">§{num}</span>
        <div className="h-px flex-1 bg-line" />
        <span className="section-num">{kicker}</span>
      </div>
      <h2 className="serif text-4xl sm:text-5xl md:text-6xl leading-[1.02] text-ink max-w-[20ch]">
        {title}
      </h2>
      {lede && (
        <p className="mt-5 text-ink2 text-lg max-w-[62ch] leading-relaxed">{lede}</p>
      )}
    </div>
  );
}

function Pill({ children, tone = "default" }) {
  const cls = tone === "teal" ? "chip chip-teal" : tone === "ember" ? "chip chip-ember" : tone === "dark" ? "chip chip-dark" : "chip";
  return <span className={cls}>{children}</span>;
}

function Card({ children, className = "" }) {
  return (
    <div className={`bg-[#FFFDF9] hairline rounded-2xl ${className}`}>
      {children}
    </div>
  );
}

function LabelledInput({ label, hint, children }) {
  return (
    <label className="block">
      <div className="flex items-baseline justify-between mb-1.5">
        <span className="mono text-[11px] uppercase tracking-widest text-muted">{label}</span>
        {hint && <span className="mono text-[10px] text-muted">{hint}</span>}
      </div>
      {children}
    </label>
  );
}

// Fake mini bar chart for the hero
function HeroMini() {
  const [hover, setHover] = useState(-1);
  const bars = [
    { k: "SQL",        v: 92, note: "non-negotiable" },
    { k: "Excel",      v: 78, note: "still essential" },
    { k: "Power BI",   v: 71, note: "UK favourite" },
    { k: "Python",     v: 64, note: "analyst bonus" },
    { k: "AI fluency", v: 58, note: "rising fast" },
    { k: "Git",        v: 44, note: "underrated" },
  ];
  return (
    <div className="hairline rounded-xl p-5 bg-[#FFFDF9]">
      <div className="flex items-baseline justify-between mb-4">
        <span className="mono text-[11px] uppercase tracking-widest text-muted">
          What UK data JDs ask for — 2026
        </span>
        <span className="mono text-[10px] text-muted">hover the bars</span>
      </div>
      <div className="space-y-2.5">
        {bars.map((b, i) => (
          <div key={b.k}
               onMouseEnter={() => setHover(i)} onMouseLeave={() => setHover(-1)}
               className="flex items-center gap-3 cursor-default">
            <div className="w-24 mono text-[11px] text-ink2">{b.k}</div>
            <div className="flex-1 h-5 bg-paper2 relative overflow-hidden rounded-sm">
              <div className="absolute inset-y-0 left-0 bg-teal transition-all duration-500"
                   style={{ width: `${b.v}%`, opacity: hover === -1 || hover === i ? 1 : 0.35 }}/>
              <div className="absolute inset-0 flex items-center justify-end pr-2 mono text-[10px] text-ink2">
                {b.v}%
              </div>
            </div>
            <div className="hidden sm:block w-36 mono text-[10px] text-muted">
              {hover === i ? b.note : ""}
            </div>
          </div>
        ))}
      </div>
      <div className="mt-4 pt-3 border-t border-line mono text-[10px] text-muted">
        rough blend of LinkedIn UK + Indeed UK data roles, Mar 2026 — don't quote me, trust the directions not the decimals.
      </div>
    </div>
  );
}

// Typing dots
function Thinking({ label = "thinking" }) {
  return (
    <div className="mono text-xs text-muted inline-flex items-center gap-1">
      <span>{label}</span>
      <span className="inline-flex gap-0.5">
        <span className="w-1 h-1 rounded-full bg-muted animate-pulse" style={{animationDelay:"0ms"}}/>
        <span className="w-1 h-1 rounded-full bg-muted animate-pulse" style={{animationDelay:"150ms"}}/>
        <span className="w-1 h-1 rounded-full bg-muted animate-pulse" style={{animationDelay:"300ms"}}/>
      </span>
    </div>
  );
}

function ErrorBox({ children, onRetry }) {
  if (!children) return null;
  return (
    <div className="mt-3 rounded-lg border border-ember/40 bg-[#F3DCCF]/40 p-3 flex items-start gap-2.5">
      <div className="text-ember mt-0.5"><I.Alert size={16}/></div>
      <div className="flex-1 text-sm text-ink2 leading-snug">{children}</div>
      {onRetry && (
        <button onClick={onRetry} className="mono text-[11px] text-ink2 underline underline-offset-2 hover:text-ink">
          retry
        </button>
      )}
    </div>
  );
}

function NeedKeyNotice() {
  return (
    <div className="flex items-center gap-2 mono text-[11px] text-muted">
      <I.Key size={14}/>
      <span>No API key set.&nbsp;</span>
      <a href="#api-setup" className="underline underline-offset-2 text-ink hover:text-teal">Set one in §5</a>
      <span>&nbsp;or</span>
      <a href="#projects" className="underline underline-offset-2 text-ink hover:text-teal">skip to static projects</a>
    </div>
  );
}

Object.assign(window, { APIContext, useAPI, Reveal, SectionHeader, Pill, Card, LabelledInput, HeroMini, Thinking, ErrorBox, NeedKeyNotice });
