// CrackField — the hero move.
// A full-viewport layer of crack filaments behind the content.
// Density tunes per section, drifts slowly on scroll, heals around the cursor.

const { useState: useCrackState, useEffect: useCrackEffect, useRef: useCrackRef, useMemo: useCrackMemo } = React;

// ─────────────────────────────────────────────
// Crack generator — procedural, seeded, deterministic
// ─────────────────────────────────────────────

function seedRandom(seed) {
  return () => {
    seed = (seed * 9301 + 49297) % 233280;
    return seed / 233280;
  };
}

// Generate a branching crack pattern from an impact origin.
// Returns an array of line segments {x1,y1,x2,y2,w,o}.
function generateCrack(origin, seed, branches = 7, depth = 3) {
  const rand = seedRandom(seed);
  const segs = [];
  const spokes = [];
  // Primary spokes radiating from impact
  for (let i = 0; i < branches; i++) {
    const angle = (i / branches) * Math.PI * 2 + rand() * 0.3;
    const len = 80 + rand() * 220;
    const endX = origin.x + Math.cos(angle) * len;
    const endY = origin.y + Math.sin(angle) * len;
    segs.push({
      x1: origin.x, y1: origin.y, x2: endX, y2: endY,
      w: 0.7 + rand() * 0.4, o: 0.55 + rand() * 0.3,
    });
    spokes.push({ x: endX, y: endY, angle, len });
  }
  // Branch off mid-spoke
  spokes.forEach((s, i) => {
    const nBranch = 1 + Math.floor(rand() * 3);
    for (let b = 0; b < nBranch; b++) {
      const t = 0.3 + rand() * 0.6;
      const startX = origin.x + Math.cos(s.angle) * s.len * t;
      const startY = origin.y + Math.sin(s.angle) * s.len * t;
      const branchAngle = s.angle + (rand() - 0.5) * 1.2;
      const branchLen = 40 + rand() * 100;
      segs.push({
        x1: startX, y1: startY,
        x2: startX + Math.cos(branchAngle) * branchLen,
        y2: startY + Math.sin(branchAngle) * branchLen,
        w: 0.4 + rand() * 0.3, o: 0.3 + rand() * 0.3,
      });
    }
  });
  // Concentric micro-cracks near origin
  for (let i = 0; i < 4 + Math.floor(rand() * 4); i++) {
    const a = rand() * Math.PI * 2;
    const r1 = 6 + rand() * 12;
    const r2 = r1 + 3 + rand() * 8;
    segs.push({
      x1: origin.x + Math.cos(a) * r1, y1: origin.y + Math.sin(a) * r1,
      x2: origin.x + Math.cos(a + 0.3) * r2, y2: origin.y + Math.sin(a + 0.3) * r2,
      w: 0.3, o: 0.35 + rand() * 0.25,
    });
  }
  return segs;
}

// ─────────────────────────────────────────────
// CrackField — layered behind page content
// ─────────────────────────────────────────────
// Props:
//   density: 0..1   (0 = no cracks, 1 = full shatter)
//   impacts: [{x%, y%, seed}]   (percentages of viewport)
//   height: px      (total canvas height; usually document height)
//   accent: hex     (hotspot color, defaults orange)

function CrackField({ density = 0.7, impacts, height = 4000, accent = '#FF6B1A' }) {
  const canvasRef = useCrackRef(null);
  const [scrollY, setScrollY] = useCrackState(0);
  const [mouse, setMouse] = useCrackState({ x: -9999, y: -9999, active: false });
  const [vw, setVw] = useCrackState(typeof window !== 'undefined' ? window.innerWidth : 1440);

  useCrackEffect(() => {
    const onScroll = () => setScrollY(window.scrollY);
    const onResize = () => setVw(window.innerWidth);
    const onMove = (e) => setMouse({ x: e.clientX, y: e.clientY + window.scrollY, active: true });
    const onLeave = () => setMouse(m => ({ ...m, active: false }));
    window.addEventListener('scroll', onScroll, { passive: true });
    window.addEventListener('resize', onResize);
    window.addEventListener('pointermove', onMove, { passive: true });
    window.addEventListener('pointerleave', onLeave);
    return () => {
      window.removeEventListener('scroll', onScroll);
      window.removeEventListener('resize', onResize);
      window.removeEventListener('pointermove', onMove);
      window.removeEventListener('pointerleave', onLeave);
    };
  }, []);

  // Default impacts spread through document height, density-weighted
  const resolvedImpacts = useCrackMemo(() => {
    if (impacts) return impacts;
    const out = [];
    const rand = seedRandom(8472);
    // 1 impact per ~700px of document, scaled by density
    const count = Math.floor((height / 700) * density * 1.5);
    for (let i = 0; i < count; i++) {
      out.push({
        x: 0.1 + rand() * 0.8,   // 10%..90% horizontal
        y: (i + rand() * 0.6) / count,
        seed: 1000 + i * 137,
        intensity: 0.4 + rand() * 0.6,
      });
    }
    return out;
  }, [height, density, impacts]);

  // Generate all crack segments once per impacts list
  const cracks = useCrackMemo(() => {
    return resolvedImpacts.map((imp) => {
      const origin = { x: imp.x * vw, y: imp.y * height };
      const segs = generateCrack(
        origin, imp.seed,
        Math.round(5 + (imp.intensity || 1) * 5),
      );
      return { origin, segs, intensity: imp.intensity || 1 };
    });
  }, [resolvedImpacts, vw, height]);

  // Parallax: cracks drift upward slightly slower than content
  const parallaxY = scrollY * 0.15;

  return (
    <svg
      aria-hidden="true"
      data-recolor="cracks"
      style={{
        position: 'absolute', top: 0, left: 0,
        width: '100%', height,
        pointerEvents: 'none',
        zIndex: 0,
        mixBlendMode: 'var(--crack-blend, screen)',
        opacity: 'var(--crack-opacity, 0.55)',
      }}
      width={vw} height={height}
      viewBox={`0 0 ${vw} ${height}`}
    >
      <defs>
        <radialGradient id="crack-hotspot" cx="50%" cy="50%" r="50%">
          <stop offset="0%" stopColor={accent} stopOpacity="0.35"/>
          <stop offset="45%" stopColor={accent} stopOpacity="0.08"/>
          <stop offset="100%" stopColor={accent} stopOpacity="0"/>
        </radialGradient>
        <radialGradient id="crack-heal" cx="50%" cy="50%" r="50%">
          <stop offset="0%" stopColor="#000" stopOpacity="1"/>
          <stop offset="70%" stopColor="#000" stopOpacity="0.6"/>
          <stop offset="100%" stopColor="#000" stopOpacity="0"/>
        </radialGradient>
        <mask id="crack-mask">
          <rect width={vw} height={height} fill="white"/>
          {/* Cursor heal zone — cracks fade near cursor */}
          {mouse.active && (
            <circle cx={mouse.x} cy={mouse.y} r="180" fill="url(#crack-heal)" />
          )}
        </mask>
      </defs>

      <g
        transform={`translate(0, ${-parallaxY})`}
        mask="url(#crack-mask)"
      >
        {cracks.map((c, i) => (
          <g key={i}>
            {/* soft orange hotspot at origin */}
            <circle
              cx={c.origin.x} cy={c.origin.y}
              r={40 + c.intensity * 30}
              fill="url(#crack-hotspot)"
            />
            {/* crack segments — white, subtle */}
            {c.segs.map((s, j) => (
              <line key={j}
                x1={s.x1} y1={s.y1} x2={s.x2} y2={s.y2}
                stroke="var(--crack-fg, #ffffff)"
                strokeWidth={s.w}
                strokeLinecap="round"
                opacity={s.o * density * 0.55}
              />
            ))}
            {/* impact origin dot */}
            <circle
              cx={c.origin.x} cy={c.origin.y} r="1.2"
              fill={accent}
              opacity={0.9 * c.intensity}
            />
          </g>
        ))}
      </g>
    </svg>
  );
}

// ─────────────────────────────────────────────
// SolderingIronGlow — cursor-following orange radial
// desktop only; hides on touch devices.
// ─────────────────────────────────────────────
function SolderingIronGlow() {
  const [pos, setPos] = useCrackState({ x: -1000, y: -1000, visible: false });

  useCrackEffect(() => {
    // Skip on touch devices
    if (window.matchMedia('(pointer: coarse)').matches) return;
    const onMove = (e) => setPos({ x: e.clientX, y: e.clientY, visible: true });
    const onLeave = () => setPos(p => ({ ...p, visible: false }));
    window.addEventListener('pointermove', onMove, { passive: true });
    window.addEventListener('pointerleave', onLeave);
    return () => {
      window.removeEventListener('pointermove', onMove);
      window.removeEventListener('pointerleave', onLeave);
    };
  }, []);

  return (
    <div style={{
      position: 'fixed',
      top: 0, left: 0,
      width: 300, height: 300,
      borderRadius: '50%',
      transform: `translate(${pos.x - 150}px, ${pos.y - 150}px)`,
      background: 'radial-gradient(circle, rgba(255,107,26,0.15) 0%, rgba(255,107,26,0.06) 30%, rgba(255,107,26,0) 70%)',
      pointerEvents: 'none',
      zIndex: 3,
      opacity: pos.visible ? 1 : 0,
      transition: 'opacity 400ms ease',
      mixBlendMode: 'screen',
      willChange: 'transform',
    }} />
  );
}

// ─────────────────────────────────────────────
// RepairCounter — live-ticking "X,XXX fixed since 2012"
// ─────────────────────────────────────────────
function RepairCounter({ style }) {
  // base number grows ~6/hour; start from epoch 2012-03-01
  const start = new Date('2012-03-01').getTime();
  const minutesSinceStart = (Date.now() - start) / 60000;
  const initial = Math.floor(14200 + minutesSinceStart * 0.0042); // ~47k by 2026
  const [count, setCount] = useCrackState(initial);
  const [pulse, setPulse] = useCrackState(false);

  useCrackEffect(() => {
    // Tick up every 12-25s with a little flash
    let t;
    const tick = () => {
      setCount(c => c + 1);
      setPulse(true);
      setTimeout(() => setPulse(false), 600);
      t = setTimeout(tick, 12000 + Math.random() * 13000);
    };
    t = setTimeout(tick, 8000);
    return () => clearTimeout(t);
  }, []);

  return (
    <div style={{
      display: 'inline-flex', alignItems: 'center', gap: 8,
      fontFamily: 'JetBrains Mono, monospace', fontSize: 11,
      color: 'var(--fg-2)', letterSpacing: '0.1em',
      whiteSpace: 'nowrap',
      ...style,
    }}>
      <span style={{
        width: 6, height: 6, borderRadius: '50%',
        background: '#FF6B1A',
        boxShadow: pulse ? '0 0 12px #FF6B1A' : '0 0 4px #FF6B1A',
        transition: 'box-shadow 600ms',
      }} />
      <span style={{ fontVariantNumeric: 'tabular-nums' }}>
        {count.toLocaleString('en-GB')} FIXED
      </span>
    </div>
  );
}

Object.assign(window, { CrackField, SolderingIronGlow, RepairCounter });
