/**
 * BatteryPanel.jsx — Battery state monitoring.
 *
 * Topics:
 *   /saltybot/balance_state  (std_msgs/String JSON)
 *     Fields: motor_cmd, state, mode (no direct voltage yet)
 *   /diagnostics             (diagnostic_msgs/DiagnosticArray)
 *     KeyValues: battery_voltage_v, battery_current_a, battery_soc_pct
 *
 * NOTE: Dedicated /saltybot/battery (sensor_msgs/BatteryState) can be added
 *       to cmd_vel_bridge_node once firmware sends voltage/current over USB.
 *       The panel will pick it up automatically from /diagnostics KeyValues.
 *
 * 4S LiPo range: 12.0 V (empty) → 16.8 V (full)
 */

import { useEffect, useRef, useState } from 'react';

const LIPO_4S_MIN = 12.0;
const LIPO_4S_MAX = 16.8;
const HISTORY_MAX = 120; // 2 min at 1 Hz

function socFromVoltage(v) {
  if (v <= 0) return null;
  return Math.max(0, Math.min(100, ((v - LIPO_4S_MIN) / (LIPO_4S_MAX - LIPO_4S_MIN)) * 100));
}

function voltColor(v) {
  const soc = socFromVoltage(v);
  if (soc === null) return '#6b7280';
  if (soc > 50) return '#22c55e';
  if (soc > 20) return '#f59e0b';
  return '#ef4444';
}

function SparklineCanvas({ data, width = 280, height = 60 }) {
  const ref = useRef(null);

  useEffect(() => {
    const canvas = ref.current;
    if (!canvas || data.length < 2) return;
    const ctx = canvas.getContext('2d');
    const W = canvas.width, H = canvas.height;
    ctx.clearRect(0, 0, W, H);

    // Background
    ctx.fillStyle = '#020208';
    ctx.fillRect(0, 0, W, H);

    // Grid lines at 25% / 50% / 75%
    [25, 50, 75].forEach(pct => {
      const y = H - (pct / 100) * H;
      ctx.strokeStyle = 'rgba(0,255,255,0.05)';
      ctx.lineWidth = 0.5;
      ctx.beginPath(); ctx.moveTo(0, y); ctx.lineTo(W, y); ctx.stroke();
    });

    // Voltage range for y-axis
    const minV = Math.min(LIPO_4S_MIN, ...data);
    const maxV = Math.max(LIPO_4S_MAX, ...data);
    const rangeV = maxV - minV || 1;

    // Line
    ctx.strokeStyle = '#06b6d4';
    ctx.lineWidth = 1.5;
    ctx.beginPath();
    data.forEach((v, i) => {
      const x = (i / (data.length - 1)) * W;
      const y = H - ((v - minV) / rangeV) * H * 0.9 - H * 0.05;
      i === 0 ? ctx.moveTo(x, y) : ctx.lineTo(x, y);
    });
    ctx.stroke();

    // Fill under
    ctx.lineTo(W, H); ctx.lineTo(0, H); ctx.closePath();
    ctx.fillStyle = 'rgba(6,182,212,0.08)';
    ctx.fill();

    // Latest value label
    const last = data[data.length - 1];
    ctx.fillStyle = '#06b6d4';
    ctx.font = 'bold 10px monospace';
    ctx.textAlign = 'right';
    ctx.fillText(`${last.toFixed(2)}V`, W - 3, 12);
  }, [data]);

  return (
    <canvas
      ref={ref}
      width={width}
      height={height}
      className="w-full rounded border border-gray-900 block"
    />
  );
}

export function BatteryPanel({ subscribe }) {
  const [voltage, setVoltage]   = useState(0);
  const [current, setCurrent]   = useState(null);
  const [soc, setSoc]           = useState(null);
  const [history, setHistory]   = useState([]);
  const [lastTs, setLastTs]     = useState(null);
  const lastHistoryPush = useRef(0);

  // /diagnostics — look for battery KeyValues
  useEffect(() => {
    const unsub = subscribe(
      '/diagnostics',
      'diagnostic_msgs/DiagnosticArray',
      (msg) => {
        for (const status of msg.status ?? []) {
          const kv = {};
          for (const pair of status.values ?? []) {
            kv[pair.key] = pair.value;
          }
          if (kv.battery_voltage_v !== undefined) {
            const v = parseFloat(kv.battery_voltage_v);
            setVoltage(v);
            setSoc(socFromVoltage(v));
            setLastTs(Date.now());
            // Throttle history to ~1 Hz
            const now = Date.now();
            if (now - lastHistoryPush.current >= 1000) {
              lastHistoryPush.current = now;
              setHistory(h => [...h, v].slice(-HISTORY_MAX));
            }
          }
          if (kv.battery_current_a !== undefined) {
            setCurrent(parseFloat(kv.battery_current_a));
          }
          if (kv.battery_soc_pct !== undefined) {
            setSoc(parseFloat(kv.battery_soc_pct));
          }
        }
      }
    );
    return unsub;
  }, [subscribe]);

  // Also listen to balance_state for rough motor-current proxy
  useEffect(() => {
    const unsub = subscribe('/saltybot/balance_state', 'std_msgs/String', (msg) => {
      try {
        const d = JSON.parse(msg.data);
        // motor_cmd ∈ [-1000..1000] → rough current proxy
        if (d.motor_cmd !== undefined && current === null) {
          setCurrent(Math.abs(d.motor_cmd) / 1000 * 20); // rough max 20A
        }
      } catch { /* ignore */ }
    });
    return unsub;
  }, [subscribe, current]);

  const socPct   = soc ?? socFromVoltage(voltage) ?? 0;
  const col      = voltColor(voltage);
  const stale    = lastTs && Date.now() - lastTs > 10000;
  const runtime  = (voltage > 0 && current && current > 0.1)
    ? ((socPct / 100) * 16000 / current / 60).toFixed(0) // rough Wh/V/A estimate
    : null;

  return (
    <div className="space-y-4">
      {/* Main gauges */}
      <div className="grid grid-cols-2 sm:grid-cols-4 gap-3">
        <div className="bg-gray-950 rounded-lg border border-cyan-950 p-3 col-span-2 sm:col-span-1">
          <div className="text-cyan-700 text-xs font-bold tracking-widest mb-1">VOLTAGE</div>
          <div className="text-3xl font-bold" style={{ color: col }}>
            {voltage > 0 ? voltage.toFixed(2) : '—'}
          </div>
          <div className="text-gray-600 text-xs">V {stale ? '(stale)' : ''}</div>
        </div>

        <div className="bg-gray-950 rounded-lg border border-cyan-950 p-3">
          <div className="text-cyan-700 text-xs font-bold tracking-widest mb-1">SOC</div>
          <div className="text-3xl font-bold" style={{ color: col }}>
            {socPct > 0 ? Math.round(socPct) : '—'}
          </div>
          <div className="text-gray-600 text-xs">%</div>
        </div>

        <div className="bg-gray-950 rounded-lg border border-cyan-950 p-3">
          <div className="text-cyan-700 text-xs font-bold tracking-widest mb-1">CURRENT</div>
          <div className="text-3xl font-bold text-orange-400">
            {current != null ? current.toFixed(1) : '—'}
          </div>
          <div className="text-gray-600 text-xs">A {current === null ? '' : '(est.)'}</div>
        </div>

        <div className="bg-gray-950 rounded-lg border border-cyan-950 p-3">
          <div className="text-cyan-700 text-xs font-bold tracking-widest mb-1">EST. RUN</div>
          <div className="text-3xl font-bold text-purple-400">
            {runtime ?? '—'}
          </div>
          <div className="text-gray-600 text-xs">min</div>
        </div>
      </div>

      {/* SoC bar */}
      <div className="bg-gray-950 rounded-lg border border-cyan-950 p-4">
        <div className="flex justify-between text-xs mb-2">
          <span className="text-cyan-700 font-bold tracking-widest">STATE OF CHARGE</span>
          <span style={{ color: col }}>{Math.round(socPct)}%</span>
        </div>
        <div className="w-full h-4 bg-gray-900 rounded overflow-hidden border border-gray-800">
          <div
            className="h-full transition-all duration-1000 rounded"
            style={{ width: `${socPct}%`, background: col }}
          />
        </div>
        <div className="flex justify-between text-xs mt-1 text-gray-700">
          <span>{LIPO_4S_MIN}V empty</span>
          <span>{LIPO_4S_MAX}V full</span>
        </div>
      </div>

      {/* Voltage history sparkline */}
      <div className="bg-gray-950 rounded-lg border border-cyan-950 p-4">
        <div className="text-cyan-700 text-xs font-bold tracking-widest mb-2">
          VOLTAGE HISTORY (2 min)
        </div>
        {history.length >= 2 ? (
          <SparklineCanvas data={history} height={60} />
        ) : (
          <div className="text-gray-600 text-xs text-center py-4 border border-dashed border-gray-800 rounded">
            Waiting for /diagnostics data…
            <div className="mt-1 text-gray-700 text-xs">
              Requires battery_voltage_v KeyValue in DiagnosticArray
            </div>
          </div>
        )}
      </div>
    </div>
  );
}
