/* ============================================================
   Operion WTT — SVG charts (JIT style)
   Exports to window: Sparkline, LineChart, AreaChart, BarChart,
   Gauge, Donut, TankLevel, RangeBar
   ============================================================ */
(function () {
  const { useId } = React;
  const NAVY = '#23416A', ORANGE = '#F2941F', RUN = '#1E9E5A', ALARM = '#D33A2C', CYAN = '#2E8BC0';

  function niceMax(v) {
    if (v <= 0) return 1;
    const exp = Math.pow(10, Math.floor(Math.log10(v)));
    const f = v / exp;
    const nf = f <= 1 ? 1 : f <= 2 ? 2 : f <= 5 ? 5 : 10;
    return nf * exp;
  }

  function path(pts) {
    return pts.map((p, i) => (i === 0 ? 'M' : 'L') + p[0].toFixed(1) + ' ' + p[1].toFixed(1)).join(' ');
  }

  // ---- Sparkline ----
  function Sparkline({ data, w = 96, h = 32, color = ORANGE, fill = true }) {
    if (!data || !data.length) return null;
    const min = Math.min(...data), max = Math.max(...data), rng = max - min || 1;
    const pts = data.map((v, i) => [(i / (data.length - 1)) * w, h - 3 - ((v - min) / rng) * (h - 6)]);
    const id = useId();
    return (
      React.createElement('svg', { width: w, height: h, viewBox: `0 0 ${w} ${h}`, style: { display: 'block' } },
        fill && React.createElement('defs', null,
          React.createElement('linearGradient', { id: 'sp' + id, x1: 0, y1: 0, x2: 0, y2: 1 },
            React.createElement('stop', { offset: '0%', stopColor: color, stopOpacity: 0.22 }),
            React.createElement('stop', { offset: '100%', stopColor: color, stopOpacity: 0 }))),
        fill && React.createElement('path', { d: path(pts) + ` L${w} ${h} L0 ${h} Z`, fill: 'url(#sp' + id + ')' }),
        React.createElement('path', { d: path(pts), fill: 'none', stroke: color, strokeWidth: 2, strokeLinecap: 'round', strokeLinejoin: 'round' })
      )
    );
  }

  // ---- Axis-based chart frame ----
  function Frame({ w, h, pad, max, min = 0, ticks = 4, children, xLabels }) {
    const lines = [];
    for (let i = 0; i <= ticks; i++) {
      const y = pad.t + (i / ticks) * (h - pad.t - pad.b);
      const val = max - (i / ticks) * (max - min);
      lines.push(React.createElement('g', { key: i },
        React.createElement('line', { x1: pad.l, y1: y, x2: w - pad.r, y2: y, stroke: 'var(--border)', strokeWidth: 1, strokeDasharray: i === ticks ? '0' : '3 4' }),
        React.createElement('text', { x: pad.l - 8, y: y + 3.5, textAnchor: 'end', fontSize: 10, fontFamily: 'IBM Plex Mono, monospace', fill: 'var(--fg-3)' }, formatTick(val))
      ));
    }
    return React.createElement('svg', { width: '100%', height: h, viewBox: `0 0 ${w} ${h}`, style: { display: 'block', overflow: 'visible' } },
      lines, children,
      xLabels && xLabels.map((lb, i) => {
        const x = pad.l + (i / (xLabels.length - 1)) * (w - pad.l - pad.r);
        return React.createElement('text', { key: 'x' + i, x, y: h - pad.b + 14, textAnchor: 'middle', fontSize: 9.5, fontFamily: 'IBM Plex Mono, monospace', fill: 'var(--fg-3)' }, lb);
      })
    );
  }
  function formatTick(v) {
    if (Math.abs(v) >= 1000) return (v / 1000).toFixed(1) + 'k';
    return Math.abs(v) < 10 ? v.toFixed(1) : Math.round(v);
  }

  function scaleY(v, max, min, h, pad) { return pad.t + (1 - (v - min) / (max - min)) * (h - pad.t - pad.b); }
  function scaleX(i, n, w, pad) { return pad.l + (i / (n - 1)) * (w - pad.l - pad.r); }

  // ---- LineChart (one or more series) ----
  function LineChart({ series, w = 520, h = 200, colors = [NAVY, ORANGE, RUN], xLabels, fixedMax, fixedMin }) {
    const pad = { t: 12, r: 14, b: 22, l: 38 };
    const all = series.flatMap((s) => s.data);
    const max = fixedMax != null ? fixedMax : niceMax(Math.max(...all) * 1.1);
    const min = fixedMin != null ? fixedMin : 0;
    const n = series[0].data.length;
    return React.createElement(Frame, { w, h, pad, max, min, xLabels },
      series.map((s, si) => {
        const c = s.color || colors[si % colors.length];
        const pts = s.data.map((v, i) => [scaleX(i, n, w, pad), scaleY(v, max, min, h, pad)]);
        return React.createElement('g', { key: si },
          React.createElement('path', { d: path(pts), fill: 'none', stroke: c, strokeWidth: 2.2, strokeLinecap: 'round', strokeLinejoin: 'round' }),
          React.createElement('circle', { cx: pts[pts.length - 1][0], cy: pts[pts.length - 1][1], r: 3, fill: c })
        );
      })
    );
  }

  // ---- AreaChart ----
  function AreaChart({ data, w = 520, h = 200, color = CYAN, xLabels, fixedMax }) {
    const pad = { t: 12, r: 14, b: 22, l: 38 };
    const max = fixedMax != null ? fixedMax : niceMax(Math.max(...data) * 1.15);
    const n = data.length;
    const pts = data.map((v, i) => [scaleX(i, n, w, pad), scaleY(v, max, 0, h, pad)]);
    const id = useId();
    return React.createElement(Frame, { w, h, pad, max, xLabels },
      React.createElement('defs', null,
        React.createElement('linearGradient', { id: 'ar' + id, x1: 0, y1: 0, x2: 0, y2: 1 },
          React.createElement('stop', { offset: '0%', stopColor: color, stopOpacity: 0.28 }),
          React.createElement('stop', { offset: '100%', stopColor: color, stopOpacity: 0.02 }))),
      React.createElement('path', { d: path(pts) + ` L${pts[n - 1][0]} ${h - pad.b} L${pts[0][0]} ${h - pad.b} Z`, fill: 'url(#ar' + id + ')' }),
      React.createElement('path', { d: path(pts), fill: 'none', stroke: color, strokeWidth: 2.2, strokeLinecap: 'round', strokeLinejoin: 'round' })
    );
  }

  // ---- BarChart (vertical or grouped) ----
  function BarChart({ data, w = 520, h = 200, color = NAVY, xLabels, horizontal = false, labels, fixedMax }) {
    const pad = horizontal ? { t: 8, r: 40, b: 8, l: 110 } : { t: 12, r: 14, b: 22, l: 38 };
    const max = fixedMax != null ? fixedMax : niceMax(Math.max(...data) * 1.12);
    const n = data.length;
    if (horizontal) {
      const bh = (h - pad.t - pad.b) / n;
      return React.createElement('svg', { width: '100%', height: h, viewBox: `0 0 ${w} ${h}`, style: { display: 'block', overflow: 'visible' } },
        data.map((v, i) => {
          const y = pad.t + i * bh + bh * 0.18;
          const bw = ((v / max) * (w - pad.l - pad.r));
          return React.createElement('g', { key: i },
            React.createElement('text', { x: pad.l - 10, y: y + bh * 0.42, textAnchor: 'end', fontSize: 11, fill: 'var(--fg-2)', fontWeight: 600 }, labels ? labels[i] : ''),
            React.createElement('rect', { x: pad.l, y, width: Math.max(2, bw), height: bh * 0.64, rx: 3, fill: Array.isArray(color) ? color[i % color.length] : color }),
            React.createElement('text', { x: pad.l + bw + 6, y: y + bh * 0.42, fontSize: 10.5, fontFamily: 'IBM Plex Mono, monospace', fill: 'var(--fg-2)', fontWeight: 600 }, formatTick(v))
          );
        })
      );
    }
    const bw = (w - pad.l - pad.r) / n * 0.62;
    const gap = (w - pad.l - pad.r) / n;
    return React.createElement(Frame, { w, h, pad, max, xLabels },
      data.map((v, i) => {
        const x = pad.l + i * gap + (gap - bw) / 2;
        const bh2 = (v / max) * (h - pad.t - pad.b);
        return React.createElement('rect', { key: i, x, y: h - pad.b - bh2, width: bw, height: Math.max(1, bh2), rx: 2.5, fill: Array.isArray(color) ? color[i % color.length] : color });
      })
    );
  }

  // ---- Gauge (radial arc) ----
  function Gauge({ value, max = 100, min = 0, size = 130, label, unit, color, thresholds }) {
    const pct = (value - min) / (max - min);
    const startA = 135, endA = 405; // 270deg sweep
    const ang = startA + pct * (endA - startA);
    const r = size / 2 - 14;
    const cx = size / 2, cy = size / 2;
    const toXY = (a) => [cx + r * Math.cos((a * Math.PI) / 180), cy + r * Math.sin((a * Math.PI) / 180)];
    const [sx, sy] = toXY(startA), [ex, ey] = toXY(endA), [vx, vy] = toXY(ang);
    const big = (endA - startA) > 180 ? 1 : 0;
    const bigv = (ang - startA) > 180 ? 1 : 0;
    let col = color || NAVY;
    if (thresholds) { col = pct >= thresholds[1] ? ALARM : pct >= thresholds[0] ? ORANGE : RUN; }
    return React.createElement('div', { style: { textAlign: 'center' } },
      React.createElement('svg', { width: size, height: size * 0.86, viewBox: `0 0 ${size} ${size * 0.86}` },
        React.createElement('path', { d: `M${sx} ${sy} A${r} ${r} 0 ${big} 1 ${ex} ${ey}`, fill: 'none', stroke: 'var(--bg-sunken)', strokeWidth: 10, strokeLinecap: 'round' }),
        React.createElement('path', { d: `M${sx} ${sy} A${r} ${r} 0 ${bigv} 1 ${vx} ${vy}`, fill: 'none', stroke: col, strokeWidth: 10, strokeLinecap: 'round' }),
        React.createElement('text', { x: cx, y: cy + 2, textAnchor: 'middle', fontSize: size * 0.2, fontFamily: 'IBM Plex Mono, monospace', fontWeight: 700, fill: 'var(--fg-1)' }, typeof value === 'number' ? (value % 1 === 0 ? value : value.toFixed(1)) : value),
        unit && React.createElement('text', { x: cx, y: cy + size * 0.16, textAnchor: 'middle', fontSize: 11, fill: 'var(--fg-3)', fontFamily: 'IBM Plex Mono, monospace' }, unit)
      ),
      label && React.createElement('div', { style: { fontSize: 12.5, color: 'var(--fg-2)', fontWeight: 600, marginTop: -4 } }, label)
    );
  }

  // ---- Donut ----
  function Donut({ value, size = 96, stroke = 11, color = RUN, track = 'var(--bg-sunken)', label }) {
    const r = (size - stroke) / 2, c = 2 * Math.PI * r;
    const off = c * (1 - value / 100);
    return React.createElement('div', { style: { position: 'relative', width: size, height: size } },
      React.createElement('svg', { width: size, height: size, style: { transform: 'rotate(-90deg)' } },
        React.createElement('circle', { cx: size / 2, cy: size / 2, r, fill: 'none', stroke: track, strokeWidth: stroke }),
        React.createElement('circle', { cx: size / 2, cy: size / 2, r, fill: 'none', stroke: color, strokeWidth: stroke, strokeDasharray: c, strokeDashoffset: off, strokeLinecap: 'round', style: { transition: 'stroke-dashoffset .5s' } })
      ),
      React.createElement('div', { style: { position: 'absolute', inset: 0, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center' } },
        React.createElement('span', { style: { fontFamily: 'IBM Plex Mono, monospace', fontWeight: 700, fontSize: size * 0.22, color: 'var(--fg-1)' } }, Math.round(value) + '%'),
        label && React.createElement('span', { style: { fontSize: 10, color: 'var(--fg-3)' } }, label))
    );
  }

  // ---- TankLevel (vertical) ----
  function TankLevel({ level, w = 56, h = 92, alarm, color = CYAN }) {
    const fillH = (level / 100) * (h - 6);
    let col = color;
    if (alarm === 'high' && level > 85) col = ALARM;
    else if (alarm === 'low' && level < 20) col = ALARM;
    else if (level > 90 || level < 12) col = ORANGE;
    const id = useId();
    return React.createElement('svg', { width: w, height: h, viewBox: `0 0 ${w} ${h}` },
      React.createElement('defs', null,
        React.createElement('linearGradient', { id: 'tk' + id, x1: 0, y1: 0, x2: 0, y2: 1 },
          React.createElement('stop', { offset: '0%', stopColor: col, stopOpacity: 0.75 }),
          React.createElement('stop', { offset: '100%', stopColor: col, stopOpacity: 0.95 }))),
      React.createElement('rect', { x: 1, y: 1, width: w - 2, height: h - 2, rx: 7, fill: 'var(--bg-sunken)', stroke: 'var(--border-strong)', strokeWidth: 1.5 }),
      React.createElement('rect', { x: 3, y: h - 3 - fillH, width: w - 6, height: fillH, rx: 5, fill: 'url(#tk' + id + ')', style: { transition: 'height .5s, y .5s' } }),
      // level marks
      [25, 50, 75].map((m) => React.createElement('line', { key: m, x1: w - 9, y1: h - 3 - (m / 100) * (h - 6), x2: w - 3, y2: h - 3 - (m / 100) * (h - 6), stroke: 'var(--border-strong)', strokeWidth: 1 })),
      React.createElement('text', { x: w / 2, y: h / 2 + 4, textAnchor: 'middle', fontSize: 13, fontFamily: 'IBM Plex Mono, monospace', fontWeight: 700, fill: level > 50 ? '#fff' : 'var(--fg-1)' }, level + '%')
    );
  }

  // ---- RangeBar (value within min/max band) ----
  function RangeBar({ value, min, max, lo, hi, unit }) {
    // lo/hi are the acceptable band; min/max the scale
    const pos = (v) => ((v - min) / (max - min)) * 100;
    const inBand = value >= lo && value <= hi;
    return React.createElement('div', { style: { width: '100%' } },
      React.createElement('div', { style: { position: 'relative', height: 8, background: 'var(--bg-sunken)', borderRadius: 4, border: '1px solid var(--border)', overflow: 'hidden' } },
        React.createElement('div', { style: { position: 'absolute', left: pos(lo) + '%', width: (pos(hi) - pos(lo)) + '%', top: 0, bottom: 0, background: 'var(--status-run-bg)' } }),
        React.createElement('div', { style: { position: 'absolute', left: `calc(${Math.max(0, Math.min(100, pos(value)))}% - 1px)`, top: -2, bottom: -2, width: 3, borderRadius: 2, background: inBand ? RUN : ALARM } })
      )
    );
  }

  Object.assign(window, { Sparkline, LineChart, AreaChart, BarChart, Gauge, Donut, TankLevel, RangeBar });
})();
