/**
 * BatteryChart.jsx — Battery voltage and percentage history chart
 *
 * Features:
 *   - Subscribes to /saltybot/battery_state for real-time battery data
 *   - Maintains rolling 30-minute history of readings
 *   - Dual-axis line chart: voltage (left) and percentage (right)
 *   - Canvas-based rendering for performance
 *   - Automatic rate calculation: charge/discharge in mV/min and %/min
 *   - Grid overlay, axis labels, and legend
 *   - Responsive sizing
 */

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

const MAX_HISTORY_MINUTES = 30;
const DATA_POINTS_PER_MINUTE = 2; // Sample every 30 seconds
const MAX_DATA_POINTS = MAX_HISTORY_MINUTES * DATA_POINTS_PER_MINUTE;

function formatTime(minutes) {
  if (minutes === 0) return 'now';
  if (minutes < 60) return `${minutes}m ago`;
  const hours = Math.floor(minutes / 60);
  const mins = minutes % 60;
  return `${hours}h ${mins}m ago`;
}

function calculateRate(data, field, minutes = 5) {
  // Calculate rate of change over the last N minutes
  if (data.length < 2) return 0;

  const recentMinutes = minutes;
  const now = data[data.length - 1].timestamp;
  const startTime = now - recentMinutes * 60 * 1000;

  let startValue = null;
  let startIdx = -1;

  for (let i = 0; i < data.length; i++) {
    if (data[i].timestamp >= startTime) {
      startIdx = i;
      break;
    }
  }

  if (startIdx === -1 || startIdx === data.length - 1) {
    return 0;
  }

  startValue = data[startIdx][field];
  const endValue = data[data.length - 1][field];
  const elapsedMinutes = (now - data[startIdx].timestamp) / (60 * 1000);

  return (endValue - startValue) / elapsedMinutes;
}

export function BatteryChart({ subscribe }) {
  const canvasRef = useRef(null);
  const [data, setData] = useState([]);
  const dataRef = useRef([]);
  const [stats, setStats] = useState({
    voltage: 0,
    percentage: 0,
    voltageRate: 0,
    percentageRate: 0,
  });

  // Subscribe to battery state
  useEffect(() => {
    const unsubscribe = subscribe(
      '/saltybot/battery_state',
      'std_msgs/Float32MultiArray',
      (msg) => {
        try {
          // Expect array with [voltage_mv, percentage]
          // or individual fields
          let voltage = 0;
          let percentage = 0;

          if (msg.data && msg.data.length >= 2) {
            voltage = msg.data[0]; // mV
            percentage = msg.data[1]; // 0-100
          } else if (msg.voltage !== undefined && msg.percentage !== undefined) {
            voltage = msg.voltage;
            percentage = msg.percentage;
          }

          const timestamp = Date.now();
          const newPoint = { timestamp, voltage, percentage };

          setData((prev) => {
            const updated = [...prev, newPoint];

            // Keep only last 30 minutes of data
            const thirtyMinutesAgo = timestamp - MAX_HISTORY_MINUTES * 60 * 1000;
            const filtered = updated.filter((p) => p.timestamp >= thirtyMinutesAgo);

            dataRef.current = filtered;

            // Calculate rates
            if (filtered.length >= 2) {
              setStats({
                voltage: voltage.toFixed(2),
                percentage: percentage.toFixed(1),
                voltageRate: calculateRate(filtered, 'voltage', 5),
                percentageRate: calculateRate(filtered, 'percentage', 5),
              });
            }

            return filtered;
          });
        } catch (e) {
          console.error('Error parsing battery state:', e);
        }
      }
    );

    return unsubscribe;
  }, [subscribe]);

  // Canvas rendering
  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas || dataRef.current.length === 0) return;

    const ctx = canvas.getContext('2d');
    const width = canvas.width;
    const height = canvas.height;

    // Clear canvas
    ctx.fillStyle = '#1f2937';
    ctx.fillRect(0, 0, width, height);

    const data = dataRef.current;
    const padding = { top: 30, right: 60, bottom: 40, left: 60 };
    const chartWidth = width - padding.left - padding.right;
    const chartHeight = height - padding.top - padding.bottom;

    // Find min/max values for scaling
    let minVoltage = Infinity;
    let maxVoltage = -Infinity;
    let minPercentage = Infinity;
    let maxPercentage = -Infinity;

    data.forEach((point) => {
      minVoltage = Math.min(minVoltage, point.voltage);
      maxVoltage = Math.max(maxVoltage, point.voltage);
      minPercentage = Math.min(minPercentage, point.percentage);
      maxPercentage = Math.max(maxPercentage, point.percentage);
    });

    // Add 5% padding to ranges
    const voltageRange = maxVoltage - minVoltage || 1;
    const percentageRange = maxPercentage - minPercentage || 1;
    minVoltage -= voltageRange * 0.05;
    maxVoltage += voltageRange * 0.05;
    minPercentage -= percentageRange * 0.05;
    maxPercentage += percentageRange * 0.05;

    const startTime = data[0].timestamp;
    const endTime = data[data.length - 1].timestamp;
    const timeRange = endTime - startTime || 1;

    // Grid
    ctx.strokeStyle = '#374151';
    ctx.lineWidth = 0.5;
    ctx.globalAlpha = 0.3;

    for (let i = 0; i <= 5; i++) {
      const y = padding.top + (i * chartHeight) / 5;
      ctx.beginPath();
      ctx.moveTo(padding.left, y);
      ctx.lineTo(width - padding.right, y);
      ctx.stroke();
    }

    for (let i = 0; i <= 4; i++) {
      const x = padding.left + (i * chartWidth) / 4;
      ctx.beginPath();
      ctx.moveTo(x, padding.top);
      ctx.lineTo(x, height - padding.bottom);
      ctx.stroke();
    }

    ctx.globalAlpha = 1.0;

    // Draw axes
    ctx.strokeStyle = '#6b7280';
    ctx.lineWidth = 1;
    ctx.beginPath();
    ctx.moveTo(padding.left, padding.top);
    ctx.lineTo(padding.left, height - padding.bottom);
    ctx.lineTo(width - padding.right, height - padding.bottom);
    ctx.stroke();

    // Voltage line (cyan)
    ctx.strokeStyle = '#06b6d4';
    ctx.lineWidth = 2;
    ctx.globalAlpha = 0.8;
    ctx.beginPath();

    let firstPoint = true;
    data.forEach((point) => {
      const x = padding.left + ((point.timestamp - startTime) / timeRange) * chartWidth;
      const y =
        padding.top +
        chartHeight -
        ((point.voltage - minVoltage) / (maxVoltage - minVoltage)) * chartHeight;

      if (firstPoint) {
        ctx.moveTo(x, y);
        firstPoint = false;
      } else {
        ctx.lineTo(x, y);
      }
    });
    ctx.stroke();

    // Percentage line (amber)
    ctx.strokeStyle = '#f59e0b';
    ctx.lineWidth = 2;
    ctx.globalAlpha = 0.8;
    ctx.beginPath();

    firstPoint = true;
    data.forEach((point) => {
      const x = padding.left + ((point.timestamp - startTime) / timeRange) * chartWidth;
      const y =
        padding.top +
        chartHeight -
        ((point.percentage - minPercentage) / (maxPercentage - minPercentage)) * chartHeight;

      if (firstPoint) {
        ctx.moveTo(x, y);
        firstPoint = false;
      } else {
        ctx.lineTo(x, y);
      }
    });
    ctx.stroke();

    ctx.globalAlpha = 1.0;

    // Left axis labels (voltage)
    ctx.fillStyle = '#06b6d4';
    ctx.font = 'bold 11px monospace';
    ctx.textAlign = 'right';
    for (let i = 0; i <= 5; i++) {
      const value = minVoltage + (i * (maxVoltage - minVoltage)) / 5;
      const y = padding.top + (5 - i) * (chartHeight / 5);
      ctx.fillText(value.toFixed(0), padding.left - 10, y + 4);
    }

    // Right axis labels (percentage)
    ctx.fillStyle = '#f59e0b';
    ctx.textAlign = 'left';
    for (let i = 0; i <= 5; i++) {
      const value = minPercentage + (i * (maxPercentage - minPercentage)) / 5;
      const y = padding.top + (5 - i) * (chartHeight / 5);
      ctx.fillText(value.toFixed(0) + '%', width - padding.right + 10, y + 4);
    }

    // Time axis labels
    ctx.fillStyle = '#9ca3af';
    ctx.font = '10px monospace';
    ctx.textAlign = 'center';
    for (let i = 0; i <= 4; i++) {
      const minutesAgo = MAX_HISTORY_MINUTES - (i * MAX_HISTORY_MINUTES) / 4;
      const label = formatTime(Math.floor(minutesAgo));
      const x = padding.left + (i * chartWidth) / 4;
      ctx.fillText(label, x, height - padding.bottom + 20);
    }

    // Legend
    const legendY = 10;
    ctx.font = 'bold 12px monospace';

    ctx.fillStyle = '#06b6d4';
    ctx.fillRect(width - 200, legendY, 10, 10);
    ctx.fillStyle = '#06b6d4';
    ctx.font = '11px monospace';
    ctx.textAlign = 'left';
    ctx.fillText('Voltage (mV)', width - 185, legendY + 10);

    ctx.fillStyle = '#f59e0b';
    ctx.fillRect(width - 200, legendY + 15, 10, 10);
    ctx.fillStyle = '#f59e0b';
    ctx.fillText('Percentage (%)', width - 185, legendY + 25);
  }, []);

  const isCharging = stats.voltageRate > 0.1;
  const isDischaging = stats.voltageRate < -0.1;

  return (
    <div className="flex flex-col h-full space-y-3">
      {/* Controls */}
      <div className="bg-gray-950 rounded-lg border border-cyan-950 p-3 space-y-3">
        <div className="flex justify-between items-center flex-wrap gap-2">
          <div className="text-cyan-700 text-xs font-bold tracking-widest">
            BATTERY HISTORY (30 MIN)
          </div>
          <div className="text-gray-600 text-xs">
            {data.length} samples
          </div>
        </div>

        {/* Current stats */}
        <div className="grid grid-cols-2 gap-3">
          <div className="bg-gray-900 rounded border border-gray-800 p-2 space-y-1">
            <div className="text-gray-700 text-xs font-bold">VOLTAGE</div>
            <div className="flex items-end gap-1">
              <span className="text-lg font-mono text-cyan-400">{stats.voltage}</span>
              <span className="text-xs text-gray-600 mb-0.5">mV</span>
            </div>
            <div className={`text-xs font-mono ${
              isCharging ? 'text-green-500' : isDischaging ? 'text-red-500' : 'text-gray-600'
            }`}>
              {isCharging ? '↑' : isDischaging ? '↓' : '→'} {Math.abs(stats.voltageRate).toFixed(2)} mV/min
            </div>
          </div>

          <div className="bg-gray-900 rounded border border-gray-800 p-2 space-y-1">
            <div className="text-gray-700 text-xs font-bold">PERCENTAGE</div>
            <div className="flex items-end gap-1">
              <span className="text-lg font-mono text-amber-400">{stats.percentage}</span>
              <span className="text-xs text-gray-600 mb-0.5">%</span>
            </div>
            <div className={`text-xs font-mono ${
              stats.percentageRate > 0.1 ? 'text-green-500' : stats.percentageRate < -0.1 ? 'text-red-500' : 'text-gray-600'
            }`}>
              {stats.percentageRate > 0.1 ? '↑' : stats.percentageRate < -0.1 ? '↓' : '→'} {Math.abs(stats.percentageRate).toFixed(3)} %/min
            </div>
          </div>
        </div>
      </div>

      {/* Chart canvas */}
      <div className="flex-1 bg-gray-950 rounded-lg border border-cyan-950 overflow-hidden">
        <canvas
          ref={canvasRef}
          width={800}
          height={400}
          className="w-full h-full"
          style={{ userSelect: 'none' }}
        />
      </div>

      {/* Info panel */}
      <div className="bg-gray-950 rounded border border-gray-800 p-2 text-xs text-gray-600 space-y-1">
        <div className="flex justify-between">
          <span>Topic:</span>
          <span className="text-gray-500">/saltybot/battery_state</span>
        </div>
        <div className="flex justify-between">
          <span>History:</span>
          <span className="text-gray-500">{MAX_HISTORY_MINUTES} minutes rolling window</span>
        </div>
        <div className="flex justify-between">
          <span>Rate Calculation:</span>
          <span className="text-gray-500">Last 5 minutes average</span>
        </div>
      </div>
    </div>
  );
}
