/* ==========================================================================
   Shared primitives — used across all sections.
   Exposes on window so other Babel scripts can use them.
   ========================================================================== */

const { useState: useStatePrim, useEffect: useEffectPrim, useRef: useRefPrim } = React;

/* ---- Hooks ---- */
function useInView(options = { threshold: 0.3 }) {
  const ref = useRefPrim(null);
  const [inView, setInView] = useStatePrim(false);
  useEffectPrim(() => {
    if (!ref.current) return;
    const obs = new IntersectionObserver(([entry]) => {
      if (entry.isIntersecting) { setInView(true); obs.disconnect(); }
    }, options);
    obs.observe(ref.current);
    return () => obs.disconnect();
  }, []);
  return [ref, inView];
}

function useTyped(text, trigger, speed = 28) {
  const [out, setOut] = useStatePrim("");
  useEffectPrim(() => {
    if (!trigger) { setOut(""); return; }
    let i = 0;
    const id = setInterval(() => {
      i++;
      setOut(text.slice(0, i));
      if (i >= text.length) clearInterval(id);
    }, speed);
    return () => clearInterval(id);
  }, [trigger, text]);
  return out;
}

/* ---- Field (fillable, types on scroll) ---- */
function Field({ label, value, typed = true, colSpan = 1, speed = 28 }) {
  const [ref, inView] = useInView();
  const display = useTyped(value, inView && typed, speed);
  const final = typed ? display : value;
  const showCursor = typed && inView && display.length < value.length;
  return (
    <div className="field" ref={ref} style={colSpan > 1 ? { gridColumn: `span ${colSpan}` } : {}}>
      <span className="field-label">{label}</span>
      <span className="field-value">
        {final}
        {showCursor && <span className="cursor" />}
      </span>
    </div>
  );
}

/* ---- Part header ---- */
function PartHeader({ part, title, meta, instructions }) {
  return (
    <>
      <div className="part-header">
        <span className="part-badge">Part {part}</span>
        <span className="part-title">{title}</span>
        {meta && <span className="part-meta">{meta}</span>}
      </div>
      {instructions && (
        <div className="part-instructions">
          <span>{instructions}</span>
          <span>See instructions</span>
        </div>
      )}
    </>
  );
}

/* ---- Line items (services) ---- */
function LineItem({ num, title, desc, amount }) {
  const [ref, inView] = useInView({ threshold: 0.5 });
  return (
    <div className="line-item" ref={ref}>
      <div className="line-item-num">{num}</div>
      <div className={`line-item-checkbox ${inView ? "checked" : ""}`} />
      <div className="line-item-body">
        <div className="line-item-title">{title}</div>
        <div className="line-item-desc">{desc}</div>
      </div>
      <div className="line-item-amount">{amount || "✓ INCLUDED"}</div>
    </div>
  );
}

function LineSectionHeader({ label }) {
  return (
    <div className="line-section-header">
      <span className="label">{label}</span>
    </div>
  );
}

/* ---- Decorative barcode / QR ---- */
function Barcode({ seed = "BH1040" }) {
  const bars = [];
  let hash = 0;
  for (let i = 0; i < seed.length; i++) hash = (hash * 31 + seed.charCodeAt(i)) & 0xffff;
  for (let i = 0; i < 60; i++) {
    hash = (hash * 1103515245 + 12345) & 0x7fffffff;
    const w = 1 + (hash % 3);
    const solid = (hash >> 3) % 3 !== 0;
    bars.push(<span key={i} style={{ width: w + "px", opacity: solid ? 1 : 0 }} />);
  }
  return <div className="barcode">{bars}</div>;
}

function QR() {
  const cells = [];
  let h = 7919;
  for (let i = 0; i < 256; i++) {
    h = (h * 1103515245 + 12345) & 0x7fffffff;
    const on = (h >> 5) % 3 === 0;
    const r = Math.floor(i / 16), c = i % 16;
    const inFinder =
      (r < 4 && c < 4) || (r < 4 && c >= 12) || (r >= 12 && c < 4);
    const show = inFinder ? (r === 0 || r === 3 || r === 12 || r === 15 || c === 0 || c === 3 || c === 12 || c === 15 || (r >= 1 && r <= 2 && c >= 1 && c <= 2) || (r >= 1 && r <= 2 && c >= 13 && c <= 14) || (r >= 13 && r <= 14 && c >= 1 && c <= 2)) : on;
    cells.push(<span key={i} style={{ opacity: show ? 1 : 0 }} />);
  }
  return <div className="qr">{cells}</div>;
}

/* ---- Decorative sketches ---- */
function BuildingSketch() {
  return (
    <svg viewBox="0 0 200 240" width="160" height="192" aria-hidden="true">
      <g className="sketch">
        <line x1="10" y1="230" x2="190" y2="230" />
        <rect x="30" y="60" width="140" height="170" />
        <polygon points="20,60 100,15 180,60" />
        <line x1="100" y1="15" x2="100" y2="60" strokeDasharray="3 3"/>
        <line x1="60" y1="80" x2="60" y2="220" />
        <line x1="90" y1="80" x2="90" y2="220" />
        <line x1="110" y1="80" x2="110" y2="220" />
        <line x1="140" y1="80" x2="140" y2="220" />
        <line x1="50" y1="80" x2="150" y2="80" />
        <line x1="50" y1="220" x2="150" y2="220" />
        <rect x="85" y="180" width="30" height="50" />
        <line x1="40" y1="230" x2="160" y2="230" strokeWidth="2.5" />
        <line x1="50" y1="236" x2="150" y2="236" />
      </g>
    </svg>
  );
}

function FormSketch() {
  return (
    <svg viewBox="0 0 180 200" width="140" height="156" aria-hidden="true">
      <g className="sketch">
        <rect x="30" y="25" width="110" height="150" transform="rotate(-6 85 100)" />
        <rect x="25" y="20" width="115" height="155" transform="rotate(3 82 97)" />
        <rect x="20" y="15" width="120" height="165" />
        <line x1="20" y1="40" x2="140" y2="40" strokeWidth="2" />
        <line x1="28" y1="55" x2="132" y2="55" strokeDasharray="2 2" />
        <line x1="28" y1="68" x2="132" y2="68" strokeDasharray="2 2" />
        <line x1="28" y1="81" x2="100" y2="81" strokeDasharray="2 2" />
        <rect x="28" y="95" width="12" height="12" />
        <line x1="46" y1="101" x2="132" y2="101" strokeDasharray="2 2" />
        <rect x="28" y="115" width="12" height="12" />
        <line x1="46" y1="121" x2="132" y2="121" strokeDasharray="2 2" />
        <rect x="28" y="135" width="12" height="12" />
        <line x1="46" y1="141" x2="118" y2="141" strokeDasharray="2 2" />
        <line x1="28" y1="160" x2="90" y2="160" strokeWidth="1.5" />
        <path d="M 95 160 q 5 -8 12 -2 t 15 2 t 10 -2" />
      </g>
    </svg>
  );
}

/* ---- StatBox: numbered line item rendered as a figure cell ---- */
function StatBox({ n, k, v, accent = false }) {
  return (
    <div style={{
      padding: "18px 16px",
      borderRight: "1px solid var(--rule-thin)",
      background: accent ? "var(--paper-shadow)" : "transparent",
    }}>
      <div style={{
        fontFamily: "var(--mono)",
        fontSize: "var(--t-cap)",
        letterSpacing: "0.12em",
        textTransform: "uppercase",
        color: "var(--ink-muted)",
        marginBottom: 6,
      }}>{n}</div>
      <div style={{
        fontFamily: "var(--mono)",
        fontSize: "var(--t-num)",
        fontWeight: 800,
        lineHeight: 1,
        color: accent ? "var(--stamp-red)" : "var(--ink)",
      }}>{k}</div>
      <div style={{
        fontFamily: "var(--serif)",
        fontSize: "var(--t-body)",
        color: "var(--ink-soft)",
        marginTop: 8,
        lineHeight: 1.4,
      }}>{v}</div>
    </div>
  );
}

Object.assign(window, {
  useInView, useTyped,
  Field, PartHeader, LineItem, LineSectionHeader,
  Barcode, QR,
  BuildingSketch, FormSketch,
  StatBox,
});
