/**
 * MotorCurrentGraph.jsx — Live motor current visualization
 *
 * Features:
 *   - Subscribes to /saltybot/motor_currents for real-time motor current data
 *   - Maintains rolling 60-second history of readings
 *   - Dual-axis line chart: left motor (cyan) and right motor (amber)
 *   - Canvas-based rendering for performance
 *   - Real-time peak current tracking
 *   - Average current calculation
 *   - Thermal warning threshold line (configurable)
 *   - Current stats and alerts
 */

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

const MAX_HISTORY_SECONDS = 60;
const SAMPLE_RATE = 10; // Hz
const MAX_DATA_POINTS = MAX_HISTORY_SECONDS * SAMPLE_RATE;
const THERMAL_WARNING_THRESHOLD = 25; // Amps

function calculateStats(data, field) {
  if (data.length === 0) return { current: 0, peak: 0, average: 0 };

  const values = data.map((d) => d[field]);
  const current = values[values.length - 1];
  const peak = Math.max(...values);
  const average = values.reduce((a, b) => a + b, 0) / values.length;

  return { current, peak, average };
}

export function MotorCurrentGraph({ subscribe }) {
  const canvasRef = useRef(null);
  const [data, setData] = useState([]);
  const dataRef = useRef([]);
  const [stats, setStats] = useState({
    left: { current: 0, peak: 0, average: 0 },
    right: { current: 0, peak: 0, average: 0 },
  });
  const [alerts, setAlerts] = useState({
    leftThermal: false,
    rightThermal: false,
  });

  // Subscribe to motor currents
  useEffect(() => {
    const unsubscribe = subscribe(
      '/saltybot/motor_currents',
      'std_msgs/Float32MultiArray',
      (msg) => {
        try {
          let leftAmps = 0;
          let rightAmps = 0;

          if (msg.data && msg.data.length >= 2) {
            leftAmps = Math.abs(msg.data[0]);
            rightAmps = Math.abs(msg.data[1]);
          }

          const timestamp = Date.now();
          const newPoint = { timestamp, leftAmps, rightAmps };

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

            // Keep only last 60 seconds of data
            const sixtySecondsAgo = timestamp - MAX_HISTORY_SECONDS * 1000;
            const filtered = updated.filter((p) => p.timestamp >= sixtySecondsAgo);

            dataRef.current = filtered;

            // Calculate stats
            if (filtered.length > 0) {
              const leftStats = calculateStats(filtered, 'leftAmps');
              const rightStats = calculateStats(filtered, 'rightAmps');

              setStats({
                left: leftStats,
                right: rightStats,
              });

              // Check thermal warnings
              setAlerts({
                leftThermal: leftStats.current > THERMAL_WARNING_THRESHOLD,
                rightThermal: rightStats.current > THERMAL_WARNING_THRESHOLD,
              });
            }

            return filtered;
          });
        } catch (e) {
          console.error('Error parsing motor currents:', 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 maxCurrent = 0;
    data.forEach((point) => {
      maxCurrent = Math.max(maxCurrent, point.leftAmps, point.rightAmps);
    });

    maxCurrent = maxCurrent * 1.1;
    const minCurrent = 0;

    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();

    // Draw thermal warning threshold line
    const thresholdY =
      padding.top +
      chartHeight -
      ((THERMAL_WARNING_THRESHOLD - minCurrent) / (maxCurrent - minCurrent)) * chartHeight;

    ctx.strokeStyle = '#ef4444';
    ctx.lineWidth = 1.5;
    ctx.setLineDash([4, 4]);
    ctx.globalAlpha = 0.6;
    ctx.beginPath();
    ctx.moveTo(padding.left, thresholdY);
    ctx.lineTo(width - padding.right, thresholdY);
    ctx.stroke();
    ctx.setLineDash([]);
    ctx.globalAlpha = 1.0;

    // Left motor line (cyan)
    ctx.strokeStyle = '#06b6d4';
    ctx.lineWidth = 2.5;
    ctx.globalAlpha = 0.85;
    ctx.beginPath();

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

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

    // Right motor line (amber)
    ctx.strokeStyle = '#f59e0b';
    ctx.lineWidth = 2.5;
    ctx.globalAlpha = 0.85;
    ctx.beginPath();

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

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

    ctx.globalAlpha = 1.0;

    // Y-axis labels (current in amps)
    ctx.fillStyle = '#9ca3af';
    ctx.font = 'bold 11px monospace';
    ctx.textAlign = 'right';
    for (let i = 0; i <= 5; i++) {
      const value = minCurrent + (i * (maxCurrent - minCurrent)) / 5;
      const y = padding.top + (5 - i) * (chartHeight / 5);
      ctx.fillText(value.toFixed(1), padding.left - 10, y + 4);
    }

    // X-axis time labels
    ctx.fillStyle = '#9ca3af';
    ctx.font = '10px monospace';
    ctx.textAlign = 'center';
    for (let i = 0; i <= 4; i++) {
      const secondsAgo = MAX_HISTORY_SECONDS - (i * MAX_HISTORY_SECONDS) / 4;
      const label = secondsAgo === 0 ? 'now' : `${Math.floor(secondsAgo)}s ago`;
      const x = padding.left + (i * chartWidth) / 4;
      ctx.fillText(label, x, height - padding.bottom + 20);
    }

    // Legend
    const legendY = 10;
    ctx.fillStyle = '#06b6d4';
    ctx.fillRect(width - 200, legendY, 10, 10);
    ctx.fillStyle = '#06b6d4';
    ctx.font = '11px monospace';
    ctx.textAlign = 'left';
    ctx.fillText('Left Motor', width - 185, legendY + 10);

    ctx.fillStyle = '#f59e0b';
    ctx.fillRect(width - 200, legendY + 15, 10, 10);
    ctx.fillStyle = '#f59e0b';
    ctx.fillText('Right Motor', width - 185, legendY + 25);

    ctx.fillStyle = '#ef4444';
    ctx.setLineDash([4, 4]);
    ctx.strokeStyle = '#ef4444';
    ctx.lineWidth = 1.5;
    ctx.beginPath();
    ctx.moveTo(width - 200, legendY + 37);
    ctx.lineTo(width - 190, legendY + 37);
    ctx.stroke();
    ctx.setLineDash([]);
    ctx.fillStyle = '#ef4444';
    ctx.font = '11px monospace';
    ctx.fillText('Thermal Limit', width - 185, legendY + 42);
  }, []);

  const leftThermalStatus = alerts.leftThermal ? 'THERMAL WARNING' : 'Normal';
  const rightThermalStatus = alerts.rightThermal ? 'THERMAL WARNING' : 'Normal';

  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">
            MOTOR CURRENT (60 SEC)
          </div>
          <div className="text-gray-600 text-xs">
            {data.length} samples
          </div>
        </div>

        {/* Current stats */}
        <div className="grid grid-cols-2 gap-3">
          {/* Left motor */}
          <div
            className={`rounded border p-2 space-y-1 ${
              alerts.leftThermal
                ? 'bg-red-950 border-red-800'
                : 'bg-gray-900 border-gray-800'
            }`}
          >
            <div className={`text-xs font-bold ${
              alerts.leftThermal ? 'text-red-400' : 'text-gray-700'
            }`}>
              LEFT MOTOR
            </div>
            <div className="flex items-end gap-1">
              <span className={`text-lg font-mono ${
                alerts.leftThermal ? 'text-red-400' : 'text-cyan-400'
              }`}>
                {stats.left.current.toFixed(2)}
              </span>
              <span className="text-xs text-gray-600 mb-0.5">A</span>
            </div>
            <div className="text-xs space-y-0.5">
              <div className="flex justify-between text-gray-500">
                <span>Peak:</span>
                <span className="text-cyan-300">{stats.left.peak.toFixed(2)}A</span>
              </div>
              <div className="flex justify-between text-gray-500">
                <span>Avg:</span>
                <span className="text-cyan-300">{stats.left.average.toFixed(2)}A</span>
              </div>
            </div>
            {alerts.leftThermal && (
              <div className="text-xs text-red-400 font-bold mt-1">⚠ {leftThermalStatus}</div>
            )}
          </div>

          {/* Right motor */}
          <div
            className={`rounded border p-2 space-y-1 ${
              alerts.rightThermal
                ? 'bg-red-950 border-red-800'
                : 'bg-gray-900 border-gray-800'
            }`}
          >
            <div className={`text-xs font-bold ${
              alerts.rightThermal ? 'text-red-400' : 'text-gray-700'
            }`}>
              RIGHT MOTOR
            </div>
            <div className="flex items-end gap-1">
              <span className={`text-lg font-mono ${
                alerts.rightThermal ? 'text-red-400' : 'text-amber-400'
              }`}>
                {stats.right.current.toFixed(2)}
              </span>
              <span className="text-xs text-gray-600 mb-0.5">A</span>
            </div>
            <div className="text-xs space-y-0.5">
              <div className="flex justify-between text-gray-500">
                <span>Peak:</span>
                <span className="text-amber-300">{stats.right.peak.toFixed(2)}A</span>
              </div>
              <div className="flex justify-between text-gray-500">
                <span>Avg:</span>
                <span className="text-amber-300">{stats.right.average.toFixed(2)}A</span>
              </div>
            </div>
            {alerts.rightThermal && (
              <div className="text-xs text-red-400 font-bold mt-1">⚠ {rightThermalStatus}</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/motor_currents</span>
        </div>
        <div className="flex justify-between">
          <span>History:</span>
          <span className="text-gray-500">{MAX_HISTORY_SECONDS} seconds rolling window</span>
        </div>
        <div className="flex justify-between">
          <span>Thermal Threshold:</span>
          <span className="text-gray-500">{THERMAL_WARNING_THRESHOLD}A (warning only)</span>
        </div>
      </div>
    </div>
  );
}
