/* speedometer.jsx
 * Porsche Taycan inspired arc-multi-ring tach.
 *
 * Layout (270° sweep from 7 o'clock to 5 o'clock):
 *   outer ring   — major tick marks + numerals (0, 50, 100, 150, 200+)
 *   middle ring  — minor tick marks (every 10)
 *   colored arc  — current value sweep (cool → warm)
 *   needle       — long thin pointer with counterweight stub, hub pin
 *   progress ring — case completion sweeps around the outermost rim
 *
 * Needle uses a damped spring (Hooke + critical damping) integrated each frame
 * so changes in target value cause a real overshoot + settle.
 */

const { useEffect, useRef, useState } = React;

const SPEEDO_MAX = 100;
const SPEEDO_START_ANGLE = 135;   // degrees, 0 at top, +CW. 135 = 7-ish o'clock
const SPEEDO_END_ANGLE   = 405;   // 405 = 360 + 45 → 5-ish o'clock
const SPEEDO_SWEEP       = SPEEDO_END_ANGLE - SPEEDO_START_ANGLE; // 270°

function polar(cx, cy, r, angleDeg) {
  const a = (angleDeg - 90) * Math.PI / 180;
  return [cx + r * Math.cos(a), cy + r * Math.sin(a)];
}

function arcPath(cx, cy, r, startDeg, endDeg) {
  const [x0, y0] = polar(cx, cy, r, startDeg);
  const [x1, y1] = polar(cx, cy, r, endDeg);
  const large = Math.abs(endDeg - startDeg) > 180 ? 1 : 0;
  const sweep = endDeg > startDeg ? 1 : 0;
  return `M ${x0.toFixed(2)} ${y0.toFixed(2)} A ${r} ${r} 0 ${large} ${sweep} ${x1.toFixed(2)} ${y1.toFixed(2)}`;
}

function valueToAngle(v) {
  const t = Math.max(0, Math.min(1, v / SPEEDO_MAX));
  return SPEEDO_START_ANGLE + t * SPEEDO_SWEEP;
}

/* Damped spring hook — pos chases target with overshoot. */
function useDampedNeedle(target, { stiffness = 80, damping = 9 } = {}) {
  const [pos, setPos] = useState(target);
  const posRef = useRef(target);
  const velRef = useRef(0);
  const timerRef = useRef(0);
  const lastRef = useRef(performance.now());
  const targetRef = useRef(target);

  useEffect(() => { targetRef.current = target; }, [target]);

  useEffect(() => {
    const tick = () => {
      const t = performance.now();
      const dt = Math.min(0.04, (t - lastRef.current) / 1000);
      lastRef.current = t;
      const x = posRef.current;
      const v = velRef.current;
      const k = stiffness;
      const c = damping;
      const a = -k * (x - targetRef.current) - c * v;
      const nv = v + a * dt;
      const nx = x + nv * dt;
      posRef.current = nx;
      velRef.current = nv;
      setPos(nx);
      timerRef.current = setTimeout(tick, 24);
    };
    timerRef.current = setTimeout(tick, 24);
    return () => clearTimeout(timerRef.current);
  }, [stiffness, damping]);

  return pos;
}

function Speedometer({ tokenRate, totalCases, completedCases, paused }) {
  const targetAngle = valueToAngle(tokenRate);
  const liveAngle = useDampedNeedle(targetAngle, paused ? { stiffness: 4, damping: 1.6 } : { stiffness: 80, damping: 8 });

  // Slight idle jitter (engine vibration) when not in big motion
  const [jitter, setJitter] = useState(0);
  useEffect(() => {
    let timer;
    const tick = () => {
      setJitter((Math.random() - 0.5) * (paused ? 0.4 : 1.2));
      timer = setTimeout(tick, 50);
    };
    timer = setTimeout(tick, 50);
    return () => clearTimeout(timer);
  }, [paused]);

  const finalAngle = liveAngle + jitter * 0.5;

  // Geometry
  const SIZE = 560;
  const cx = SIZE / 2;
  const cy = SIZE / 2;
  const rOuter = 240;   // tick ring
  const rMajor = 224;   // major label radius
  const rMid   = 206;   // minor tick ring
  const rArc   = 180;   // colored sweep arc
  const rFace  = 158;   // inner face boundary
  const rNeedle = 180;
  const rHub   = 22;

  // Major + minor ticks
  const majorTicks = [];
  const numMajor = 5;       // 0, 20, 40, 60, 80, 100
  for (let i = 0; i <= numMajor; i++) {
    const v = (i / numMajor) * SPEEDO_MAX;
    const ang = valueToAngle(v);
    const [x0, y0] = polar(cx, cy, rOuter, ang);
    const [x1, y1] = polar(cx, cy, rOuter - 18, ang);
    const [lx, ly] = polar(cx, cy, rMajor - 24, ang);
    const inRed = v >= 80;
    majorTicks.push({ x0, y0, x1, y1, lx, ly, label: v.toFixed(0), key: `M${i}`, inRed });
  }
  const minorTicks = [];
  for (let i = 0; i <= 100; i++) {
    if (i % 10 === 0) continue;
    const v = (i / 100) * SPEEDO_MAX;
    const ang = valueToAngle(v);
    const [x0, y0] = polar(cx, cy, rMid, ang);
    const [x1, y1] = polar(cx, cy, rMid - 10, ang);
    minorTicks.push({ x0, y0, x1, y1, key: `m${i}`, mid: i % 5 === 0 });
  }

  // Color arc (cool → warm) under needle path
  const valueArc = arcPath(cx, cy, rArc, SPEEDO_START_ANGLE, Math.max(SPEEDO_START_ANGLE + 0.5, finalAngle));
  const valueArcBg = arcPath(cx, cy, rArc, SPEEDO_START_ANGLE, SPEEDO_END_ANGLE);

  // Red zone arc at top
  const redArc = arcPath(cx, cy, rArc, valueToAngle(80), SPEEDO_END_ANGLE);

  // Case progression sweeps the outermost rim
  const progFrac = totalCases > 0 ? completedCases / totalCases : 0;
  const progArc = arcPath(
    cx, cy, rOuter + 14,
    SPEEDO_START_ANGLE,
    SPEEDO_START_ANGLE + progFrac * SPEEDO_SWEEP + 0.01
  );
  const progArcBg = arcPath(cx, cy, rOuter + 14, SPEEDO_START_ANGLE, SPEEDO_END_ANGLE);

  // Needle
  const [nx, ny] = polar(cx, cy, rNeedle, finalAngle);
  const [tailX, tailY] = polar(cx, cy, -30, finalAngle);

  // Tick-mark color for red zone
  return (
    <svg className="speedo-svg" viewBox={`0 0 ${SIZE} ${SIZE}`} aria-label="Token rate gauge">
      <defs>
        <linearGradient id="speedoArc" x1="0" y1="1" x2="1" y2="0">
          <stop offset="0%" stopColor="var(--ink-soft)" />
          <stop offset="55%" stopColor="var(--accent)" />
          <stop offset="100%" stopColor="var(--bad)" />
        </linearGradient>
        <radialGradient id="speedoFace" cx="50%" cy="50%" r="60%">
          <stop offset="0%" stopColor="var(--gauge-face)" />
          <stop offset="100%" stopColor="var(--bg-soft)" />
        </radialGradient>
      </defs>

      {/* Outer chrome ring */}
      <circle cx={cx} cy={cy} r={rOuter + 22} fill="none" stroke="var(--gauge-ring)" strokeWidth="1.5" />
      <circle cx={cx} cy={cy} r={rOuter + 8} fill="none" stroke="var(--hairline)" strokeWidth="1" />

      {/* Progress ring (case completion sweep) */}
      <path d={progArcBg} className="progress-ring-bg" />
      <path d={progArc} className="progress-ring" />

      {/* Face fill */}
      <circle cx={cx} cy={cy} r={rOuter} fill="url(#speedoFace)" stroke="var(--gauge-ring)" strokeWidth="1.5" />

      {/* Color sweep + bg track */}
      <path d={valueArcBg} fill="none" stroke="var(--gauge-tick-mute)" strokeWidth="14" strokeLinecap="butt" opacity="0.35" />
      <path d={valueArc} fill="none" stroke="url(#speedoArc)" strokeWidth="14" strokeLinecap="round" />
      <path d={redArc} fill="none" stroke="var(--bad)" strokeWidth="3" opacity="0.6" />

      {/* Minor ticks */}
      {minorTicks.map((t) => (
        <line key={t.key}
          x1={t.x0} y1={t.y0} x2={t.x1} y2={t.y1}
          stroke="var(--gauge-tick-mute)"
          strokeWidth={t.mid ? 1.4 : 0.9} />
      ))}

      {/* Major ticks + labels */}
      {majorTicks.map((t) => (
        <g key={t.key}>
          <line x1={t.x0} y1={t.y0} x2={t.x1} y2={t.y1}
            stroke={t.inRed ? "var(--bad)" : "var(--gauge-tick)"}
            strokeWidth="2.5" />
          <text
            x={t.lx} y={t.ly}
            textAnchor="middle"
            dominantBaseline="central"
            fontFamily="var(--font-mono)"
            fontSize="18"
            fontWeight="600"
            fill={t.inRed ? "var(--bad)" : "var(--ink)"}
          >
            {t.label}
          </text>
        </g>
      ))}

      {/* Inner secondary ring */}
      <circle cx={cx} cy={cy} r={rFace} fill="none" stroke="var(--hairline)" strokeWidth="1" />
      <circle cx={cx} cy={cy} r={rFace - 12} fill="none" stroke="var(--hairline)" strokeWidth="1" />

      {/* "TOKENS / SECOND" rim caption */}
      <text x={cx} y={cy - 100} textAnchor="middle"
        fontFamily="var(--font-display)" fontSize="13" letterSpacing="3"
        fill="var(--ink-mute)">
        TOKENS&nbsp;·&nbsp;SECOND
      </text>

      {/* Needle */}
      <g style={{ transformOrigin: `${cx}px ${cy}px` }}>
        <line x1={tailX} y1={tailY} x2={nx} y2={ny}
          stroke="var(--gauge-needle)" strokeWidth="3" strokeLinecap="round" />
        <circle cx={(cx*0.65 + nx*0.35)} cy={(cy*0.65 + ny*0.35)} r="4"
          fill="var(--gauge-needle)" opacity="0.6" />
      </g>

      {/* Hub */}
      <circle cx={cx} cy={cy} r={rHub} fill="var(--gauge-pin)" stroke="var(--gauge-ring)" strokeWidth="1" />
      <circle cx={cx} cy={cy} r={rHub - 7} fill="var(--gauge-needle)" />
      <circle cx={cx} cy={cy} r={rHub - 13} fill="var(--gauge-pin)" />
    </svg>
  );
}

Object.assign(window, { Speedometer, SPEEDO_MAX });
