// gauges.jsx — five gauge styles. All accept the same props:
//   { value, min, max, unit, label, decimals, thresholds, danger }
// thresholds: { warnLow, warnHigh, dangerLow, dangerHigh } (any may be null)

const fmt = (v, d = 1) => {
  if (v == null || !isFinite(v)) return '—';
  const n = Number(v);
  return d === 0 ? Math.round(n).toString() : n.toFixed(d);
};

// danger evaluator
function statusFor(v, t) {
  if (v == null) return 'idle';
  if ((t.dangerLow != null && v <= t.dangerLow) || (t.dangerHigh != null && v >= t.dangerHigh)) return 'danger';
  if ((t.warnLow != null && v <= t.warnLow) || (t.warnHigh != null && v >= t.warnHigh)) return 'warn';
  return 'ok';
}

const STATUS_COLOR = { ok: '#0a0a0a', warn: '#E5A82B', danger: '#D9342B', idle: '#9a958a' };

// ─────────────────── 1. SEMI-DIAL ───────────────────
function GaugeDial({ value, min, max, unit, label, decimals, thresholds }) {
  const hasV = value != null && isFinite(value);
  const pct = hasV ? Math.max(0, Math.min(1, (value - min) / (max - min))) : 0;
  const status = statusFor(value, thresholds);
  const color = STATUS_COLOR[status];
  const W = 220, H = 130, CX = W / 2, CY = 110, R = 90;
  const ang = a => ({ x: CX + R * Math.cos(a), y: CY + R * Math.sin(a) });
  // sweep 180° from π to 2π (left → right, top half)
  const start = Math.PI, end = 2 * Math.PI;
  const cur = start + pct * (end - start);
  const arc = (a1, a2) => {
    const p1 = ang(a1), p2 = ang(a2);
    const large = (a2 - a1) > Math.PI ? 1 : 0;
    return `M ${p1.x} ${p1.y} A ${R} ${R} 0 ${large} 1 ${p2.x} ${p2.y}`;
  };
  // danger zones on the arc
  const zoneArc = (lo, hi, fill) => {
    if (lo == null && hi == null) return null;
    const aLo = lo == null ? start : start + Math.max(0, Math.min(1, (lo - min) / (max - min))) * (end - start);
    const aHi = hi == null ? end : start + Math.max(0, Math.min(1, (hi - min) / (max - min))) * (end - start);
    if (aHi <= aLo) return null;
    return <path d={arc(aLo, aHi)} stroke={fill} strokeWidth="14" fill="none" strokeLinecap="butt" key={`${lo}-${hi}-${fill}`}/>;
  };
  return (
    <div className="gauge gauge-dial">
      <svg viewBox={`0 0 ${W} ${H}`} width="100%" preserveAspectRatio="xMidYMax meet">
        <path d={arc(start, end)} stroke="#0a0a0a" strokeWidth="14" fill="none" strokeOpacity="0.1"/>
        {zoneArc(thresholds.dangerLow != null ? min : null, thresholds.dangerLow, '#D9342B')}
        {zoneArc(thresholds.dangerHigh, thresholds.dangerHigh != null ? max : null, '#D9342B')}
        {zoneArc(thresholds.warnLow != null ? thresholds.dangerLow ?? min : null, thresholds.warnLow, '#E5A82B')}
        {zoneArc(thresholds.warnHigh, thresholds.dangerHigh ?? (thresholds.warnHigh != null ? max : null), '#E5A82B')}
        <path d={arc(start, cur)} stroke={color} strokeWidth="14" fill="none" strokeLinecap="butt"/>
        {/* needle */}
        <line x1={CX} y1={CY} x2={ang(cur).x} y2={ang(cur).y} stroke="#0a0a0a" strokeWidth="2"/>
        <circle cx={CX} cy={CY} r="5" fill="#0a0a0a"/>
      </svg>
      <div className="gauge-readout">
        <span className="gauge-value" style={{ color }}>{fmt(value, decimals)}</span>
        <span className="gauge-unit">{unit}</span>
      </div>
    </div>
  );
}

// ─────────────────── 2. RADIAL RING ───────────────────
function GaugeRing({ value, min, max, unit, decimals, thresholds }) {
  const hasV = value != null && isFinite(value);
  const pct = hasV ? Math.max(0, Math.min(1, (value - min) / (max - min))) : 0;
  const status = statusFor(value, thresholds);
  const color = STATUS_COLOR[status];
  const W = 200, R = 78, CX = W/2, CY = W/2;
  const C = 2 * Math.PI * R;
  const dash = `${C * pct} ${C}`;
  const zoneDash = (lo, hi) => {
    if (lo == null && hi == null) return null;
    const aLo = lo == null ? 0 : Math.max(0, (lo - min) / (max - min));
    const aHi = hi == null ? 1 : Math.min(1, (hi - min) / (max - min));
    return { offset: -C * aLo, length: C * (aHi - aLo) };
  };
  const dz1 = zoneDash(thresholds.dangerLow != null ? min : null, thresholds.dangerLow);
  const dz2 = zoneDash(thresholds.dangerHigh, thresholds.dangerHigh != null ? max : null);
  return (
    <div className="gauge gauge-ring">
      <svg viewBox={`0 0 ${W} ${W}`} width="100%">
        <g transform={`rotate(-90 ${CX} ${CY})`}>
          <circle cx={CX} cy={CY} r={R} fill="none" stroke="#0a0a0a" strokeOpacity="0.1" strokeWidth="14"/>
          {[dz1, dz2].map((z, i) => z && (
            <circle key={i} cx={CX} cy={CY} r={R} fill="none" stroke="#D9342B" strokeWidth="14"
              strokeDasharray={`${z.length} ${C}`} strokeDashoffset={z.offset}/>
          ))}
          <circle cx={CX} cy={CY} r={R} fill="none" stroke={color} strokeWidth="14"
            strokeDasharray={dash} strokeLinecap="butt"/>
        </g>
        <text x={CX} y={CY-2} textAnchor="middle" className="gauge-svg-num" fill={color}>{fmt(value, decimals)}</text>
        <text x={CX} y={CY+22} textAnchor="middle" className="gauge-svg-unit">{unit}</text>
      </svg>
    </div>
  );
}

// ─────────────────── 3. LINEAR BAR (default) — bar removed, readout only ───
function GaugeBar({ value, unit, decimals, thresholds }) {
  const color = STATUS_COLOR[statusFor(value, thresholds)];
  return (
    <div className="gauge gauge-bar">
      <div className="gauge-readout">
        <span className="gauge-value" style={{ color }}>{fmt(value, decimals)}</span>
        <span className="gauge-unit">{unit}</span>
      </div>
    </div>
  );
}

// ─────────────────── 4. BIG NUMBER ───────────────────
function GaugeNumber({ value, min, max, unit, decimals, thresholds }) {
  const status = statusFor(value, thresholds);
  const color = STATUS_COLOR[status];
  const hasV = value != null && isFinite(value);
  const pct = hasV ? Math.max(0, Math.min(1, (value - min) / (max - min))) : 0;
  return (
    <div className="gauge gauge-number">
      <div className="big-num" style={{ color }}>
        <span className="gauge-value">{fmt(value, decimals)}</span>
        <span className="gauge-unit">{unit}</span>
      </div>
      <div className="big-track">
        <span className="big-fill" style={{ width: `${pct * 100}%`, background: color }}/>
      </div>
      <div className="big-range">
        <span>{fmt(min, 0)}</span>
        <span className="status-pill" data-status={status}>{status === 'ok' ? 'NOMINAL' : status.toUpperCase()}</span>
        <span>{fmt(max, 0)}</span>
      </div>
    </div>
  );
}

// ─────────────────── 5. THERMOMETER / TICK SCALE ───────────────────
function GaugeScale({ value, min, max, unit, decimals, thresholds }) {
  const status = statusFor(value, thresholds);
  const color = STATUS_COLOR[status];
  const hasV = value != null && isFinite(value);
  const pct = hasV ? Math.max(0, Math.min(1, (value - min) / (max - min))) : 0;
  const W = 240, H = 90;
  const PAD = 14;
  const x = v => PAD + ((v - min) / (max - min)) * (W - PAD * 2);
  const ticks = [];
  const N = 11;
  for (let i = 0; i < N; i++) {
    const major = i % 2 === 0;
    const tx = PAD + (i / (N - 1)) * (W - PAD * 2);
    ticks.push(<line key={i} x1={tx} x2={tx} y1={H - 30} y2={H - 30 + (major ? 14 : 8)} stroke="#0a0a0a" strokeWidth={major ? 2 : 1}/>);
  }
  const zoneRect = (lo, hi, fill) => {
    if (lo == null && hi == null) return null;
    const a = lo == null ? min : Math.max(min, lo);
    const b = hi == null ? max : Math.min(max, hi);
    if (b <= a) return null;
    return <rect x={x(a)} y={H - 36} width={x(b) - x(a)} height={6} fill={fill}/>;
  };
  return (
    <div className="gauge gauge-scale">
      <svg viewBox={`0 0 ${W} ${H}`} width="100%">
        <line x1={PAD} y1={H - 30} x2={W - PAD} y2={H - 30} stroke="#0a0a0a" strokeWidth="2"/>
        {zoneRect(min, thresholds.dangerLow, '#D9342B')}
        {zoneRect(thresholds.dangerHigh, max, '#D9342B')}
        {zoneRect(thresholds.dangerLow, thresholds.warnLow, '#E5A82B')}
        {zoneRect(thresholds.warnHigh, thresholds.dangerHigh, '#E5A82B')}
        {ticks}
        {/* indicator triangle — only rendered when we have a real value, since
            x(null/NaN) would emit NaN SVG attributes that browsers silently drop. */}
        {hasV && (
          <>
            <polygon points={`${x(value)-7},${H-44} ${x(value)+7},${H-44} ${x(value)},${H-32}`} fill={color}/>
            <text x={x(value)} y={H-50} textAnchor="middle" className="gauge-svg-num" fill={color}>{fmt(value, decimals)}{unit}</text>
          </>
        )}
      </svg>
    </div>
  );
}

const GAUGE_STYLES = {
  bar:    GaugeBar,
  ring:   GaugeRing,
  dial:   GaugeDial,
  number: GaugeNumber,
  scale:  GaugeScale,
};

function Gauge(props) {
  const Comp = GAUGE_STYLES[props.style] || GaugeBar;
  return <Comp {...props}/>;
}

Object.assign(window, { Gauge, GAUGE_STYLES, statusFor, STATUS_COLOR, fmt });
