/**
 * SymbolComparisonChart Component
 * Multi-symbol overlay chart for comparing price performance
 * Epic: OQI-003 Trading Charts
 */

import React, { useMemo, useRef, useEffect, useState, useCallback } from 'react';
import {
  ChartBarSquareIcon,
  PlusIcon,
  XMarkIcon,
  ArrowPathIcon,
  Cog6ToothIcon,
  ArrowsPointingOutIcon,
  ArrowDownTrayIcon,
  EyeIcon,
  EyeSlashIcon,
} from '@heroicons/react/24/solid';

// Types
export interface PricePoint {
  timestamp: number;
  price: number;
  volume?: number;
}

export interface SymbolData {
  symbol: string;
  name: string;
  data: PricePoint[];
  color: string;
  visible: boolean;
  basePrice: number; // Starting price for normalization
  currentPrice: number;
  change: number;
  changePercent: number;
}

export type NormalizationMode = 'absolute' | 'percentage' | 'indexed';
export type TimeframeOption = '1D' | '1W' | '1M' | '3M' | '6M' | '1Y' | 'YTD' | 'ALL';

interface SymbolComparisonChartProps {
  symbols: SymbolData[];
  onAddSymbol?: () => void;
  onRemoveSymbol?: (symbol: string) => void;
  onToggleVisibility?: (symbol: string) => void;
  onRefresh?: () => void;
  onExport?: () => void;
  onTimeframeChange?: (timeframe: TimeframeOption) => void;
  isLoading?: boolean;
  height?: number;
  compact?: boolean;
}

const PRESET_COLORS = [
  '#3B82F6', // Blue
  '#10B981', // Green
  '#F59E0B', // Amber
  '#EF4444', // Red
  '#8B5CF6', // Purple
  '#EC4899', // Pink
  '#06B6D4', // Cyan
  '#84CC16', // Lime
];

const TIMEFRAMES: TimeframeOption[] = ['1D', '1W', '1M', '3M', '6M', '1Y', 'YTD', 'ALL'];

const SymbolComparisonChart: React.FC<SymbolComparisonChartProps> = ({
  symbols,
  onAddSymbol,
  onRemoveSymbol,
  onToggleVisibility,
  onRefresh,
  onExport,
  onTimeframeChange,
  isLoading = false,
  height = 400,
  compact = false,
}) => {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const containerRef = useRef<HTMLDivElement>(null);
  const [normalization, setNormalization] = useState<NormalizationMode>('percentage');
  const [timeframe, setTimeframe] = useState<TimeframeOption>('1M');
  const [showSettings, setShowSettings] = useState(false);
  const [showGrid, setShowGrid] = useState(true);
  const [showLegend, setShowLegend] = useState(true);
  const [hoveredPoint, setHoveredPoint] = useState<{
    x: number;
    y: number;
    timestamp: number;
    values: { symbol: string; value: number; color: string }[];
  } | null>(null);

  // Visible symbols only
  const visibleSymbols = useMemo(() => symbols.filter((s) => s.visible), [symbols]);

  // Normalize data based on selected mode
  const normalizedData = useMemo(() => {
    return visibleSymbols.map((symbol) => {
      const normalizedPoints = symbol.data.map((point) => {
        let value: number;
        switch (normalization) {
          case 'percentage':
            value = ((point.price - symbol.basePrice) / symbol.basePrice) * 100;
            break;
          case 'indexed':
            value = (point.price / symbol.basePrice) * 100;
            break;
          case 'absolute':
          default:
            value = point.price;
            break;
        }
        return { ...point, normalizedValue: value };
      });
      return { ...symbol, normalizedData: normalizedPoints };
    });
  }, [visibleSymbols, normalization]);

  // Calculate chart scales
  const chartMetrics = useMemo(() => {
    if (!canvasRef.current || normalizedData.length === 0) return null;

    const canvas = canvasRef.current;
    const width = canvas.width;
    const chartHeight = canvas.height;
    const padding = { top: 20, right: 80, bottom: 40, left: 60 };

    const chartWidth = width - padding.left - padding.right;
    const drawHeight = chartHeight - padding.top - padding.bottom;

    // Find min/max values and timestamps
    let minValue = Infinity;
    let maxValue = -Infinity;
    let minTime = Infinity;
    let maxTime = -Infinity;

    for (const symbol of normalizedData) {
      for (const point of symbol.normalizedData) {
        minValue = Math.min(minValue, point.normalizedValue);
        maxValue = Math.max(maxValue, point.normalizedValue);
        minTime = Math.min(minTime, point.timestamp);
        maxTime = Math.max(maxTime, point.timestamp);
      }
    }

    // Add padding to value range
    const valueRange = maxValue - minValue;
    minValue -= valueRange * 0.1;
    maxValue += valueRange * 0.1;

    return {
      width,
      chartHeight,
      chartWidth,
      drawHeight,
      padding,
      minValue,
      maxValue,
      minTime,
      maxTime,
      xScale: (timestamp: number) => {
        const normalized = (timestamp - minTime) / (maxTime - minTime);
        return padding.left + normalized * chartWidth;
      },
      yScale: (value: number) => {
        const normalized = (value - minValue) / (maxValue - minValue);
        return chartHeight - padding.bottom - normalized * drawHeight;
      },
      xInverse: (x: number) => {
        const normalized = (x - padding.left) / chartWidth;
        return minTime + normalized * (maxTime - minTime);
      },
    };
  }, [normalizedData]);

  // Draw the chart
  const drawChart = useCallback(() => {
    const canvas = canvasRef.current;
    const ctx = canvas?.getContext('2d');
    if (!canvas || !ctx || !chartMetrics) return;

    const { width, chartHeight, padding, xScale, yScale, minValue, maxValue, minTime, maxTime } = chartMetrics;

    // Clear
    ctx.clearRect(0, 0, width, chartHeight);

    // Background
    ctx.fillStyle = '#1f2937';
    ctx.fillRect(0, 0, width, chartHeight);

    // Grid
    if (showGrid) {
      ctx.strokeStyle = '#374151';
      ctx.lineWidth = 0.5;

      // Horizontal lines
      const valueStep = (maxValue - minValue) / 5;
      for (let i = 0; i <= 5; i++) {
        const value = minValue + valueStep * i;
        const y = yScale(value);
        ctx.beginPath();
        ctx.moveTo(padding.left, y);
        ctx.lineTo(width - padding.right, y);
        ctx.stroke();
      }

      // Vertical lines
      const timeStep = (maxTime - minTime) / 5;
      for (let i = 0; i <= 5; i++) {
        const time = minTime + timeStep * i;
        const x = xScale(time);
        ctx.beginPath();
        ctx.moveTo(x, padding.top);
        ctx.lineTo(x, chartHeight - padding.bottom);
        ctx.stroke();
      }
    }

    // Zero line for percentage mode
    if (normalization === 'percentage') {
      const zeroY = yScale(0);
      if (zeroY >= padding.top && zeroY <= chartHeight - padding.bottom) {
        ctx.strokeStyle = '#6b7280';
        ctx.lineWidth = 1;
        ctx.setLineDash([5, 5]);
        ctx.beginPath();
        ctx.moveTo(padding.left, zeroY);
        ctx.lineTo(width - padding.right, zeroY);
        ctx.stroke();
        ctx.setLineDash([]);
      }
    }

    // Draw each symbol's line
    for (const symbol of normalizedData) {
      if (symbol.normalizedData.length < 2) continue;

      ctx.strokeStyle = symbol.color;
      ctx.lineWidth = 2;
      ctx.beginPath();

      const firstPoint = symbol.normalizedData[0];
      ctx.moveTo(xScale(firstPoint.timestamp), yScale(firstPoint.normalizedValue));

      for (let i = 1; i < symbol.normalizedData.length; i++) {
        const point = symbol.normalizedData[i];
        ctx.lineTo(xScale(point.timestamp), yScale(point.normalizedValue));
      }

      ctx.stroke();

      // Draw endpoint marker
      const lastPoint = symbol.normalizedData[symbol.normalizedData.length - 1];
      ctx.fillStyle = symbol.color;
      ctx.beginPath();
      ctx.arc(xScale(lastPoint.timestamp), yScale(lastPoint.normalizedValue), 4, 0, Math.PI * 2);
      ctx.fill();
    }

    // Y-axis labels
    ctx.fillStyle = '#9ca3af';
    ctx.font = '10px monospace';
    ctx.textAlign = 'right';
    const valueStep = (maxValue - minValue) / 5;
    for (let i = 0; i <= 5; i++) {
      const value = minValue + valueStep * i;
      const y = yScale(value);
      const label = normalization === 'percentage' ? `${value.toFixed(1)}%` : value.toFixed(2);
      ctx.fillText(label, padding.left - 5, y + 3);
    }

    // X-axis labels
    ctx.textAlign = 'center';
    const timeStep = (maxTime - minTime) / 5;
    for (let i = 0; i <= 5; i++) {
      const time = minTime + timeStep * i;
      const x = xScale(time);
      const date = new Date(time);
      const label = date.toLocaleDateString(undefined, { month: 'short', day: 'numeric' });
      ctx.fillText(label, x, chartHeight - padding.bottom + 15);
    }

    // Right side labels (current values)
    normalizedData.forEach((symbol, index) => {
      const lastPoint = symbol.normalizedData[symbol.normalizedData.length - 1];
      if (!lastPoint) return;

      const y = yScale(lastPoint.normalizedValue);
      ctx.fillStyle = symbol.color;
      ctx.textAlign = 'left';
      ctx.font = '10px monospace';

      const label = normalization === 'percentage'
        ? `${lastPoint.normalizedValue >= 0 ? '+' : ''}${lastPoint.normalizedValue.toFixed(2)}%`
        : lastPoint.normalizedValue.toFixed(2);

      ctx.fillText(label, width - padding.right + 5, y + 3);
    });

    // Hover crosshair
    if (hoveredPoint) {
      ctx.strokeStyle = '#6b7280';
      ctx.lineWidth = 1;
      ctx.setLineDash([3, 3]);

      // Vertical line
      ctx.beginPath();
      ctx.moveTo(hoveredPoint.x, padding.top);
      ctx.lineTo(hoveredPoint.x, chartHeight - padding.bottom);
      ctx.stroke();

      ctx.setLineDash([]);
    }
  }, [chartMetrics, normalizedData, showGrid, normalization, hoveredPoint]);

  // Handle resize
  useEffect(() => {
    const container = containerRef.current;
    const canvas = canvasRef.current;
    if (!container || !canvas) return;

    const resizeObserver = new ResizeObserver((entries) => {
      for (const entry of entries) {
        canvas.width = entry.contentRect.width;
        canvas.height = height;
        drawChart();
      }
    });

    resizeObserver.observe(container);
    return () => resizeObserver.disconnect();
  }, [height, drawChart]);

  // Redraw on data change
  useEffect(() => {
    drawChart();
  }, [drawChart]);

  // Handle mouse move
  const handleMouseMove = useCallback(
    (e: React.MouseEvent<HTMLCanvasElement>) => {
      if (!chartMetrics || normalizedData.length === 0) {
        setHoveredPoint(null);
        return;
      }

      const canvas = canvasRef.current;
      if (!canvas) return;

      const rect = canvas.getBoundingClientRect();
      const x = e.clientX - rect.left;
      const y = e.clientY - rect.top;

      const { padding, xInverse, xScale, yScale } = chartMetrics;

      if (x < padding.left || x > canvas.width - padding.right) {
        setHoveredPoint(null);
        return;
      }

      const timestamp = xInverse(x);

      // Find closest points for each symbol
      const values = normalizedData.map((symbol) => {
        let closest = symbol.normalizedData[0];
        let minDist = Math.abs(timestamp - closest.timestamp);

        for (const point of symbol.normalizedData) {
          const dist = Math.abs(timestamp - point.timestamp);
          if (dist < minDist) {
            minDist = dist;
            closest = point;
          }
        }

        return {
          symbol: symbol.symbol,
          value: closest.normalizedValue,
          color: symbol.color,
        };
      });

      setHoveredPoint({ x, y, timestamp, values });
    },
    [chartMetrics, normalizedData]
  );

  const handleMouseLeave = useCallback(() => {
    setHoveredPoint(null);
  }, []);

  const handleTimeframeChange = (tf: TimeframeOption) => {
    setTimeframe(tf);
    onTimeframeChange?.(tf);
  };

  return (
    <div className={`bg-gray-800/50 rounded-lg ${compact ? 'p-2' : 'p-4'} flex flex-col`}>
      {/* Header */}
      <div className="flex items-center justify-between mb-3">
        <div className="flex items-center gap-2">
          <ChartBarSquareIcon className="w-5 h-5 text-cyan-400" />
          <h3 className={`font-semibold text-white ${compact ? 'text-xs' : 'text-sm'}`}>
            Symbol Comparison
          </h3>
          <span className="text-xs text-gray-400">
            {visibleSymbols.length} / {symbols.length} symbols
          </span>
        </div>

        <div className="flex items-center gap-1">
          {onAddSymbol && (
            <button
              onClick={onAddSymbol}
              disabled={symbols.length >= 8}
              className="p-1.5 text-gray-400 hover:text-white hover:bg-gray-700 rounded transition-colors disabled:opacity-50"
              title="Add Symbol"
            >
              <PlusIcon className="w-4 h-4" />
            </button>
          )}
          <button
            onClick={() => setShowSettings(!showSettings)}
            className={`p-1.5 rounded transition-colors ${showSettings ? 'bg-blue-500/20 text-blue-400' : 'text-gray-400 hover:text-white hover:bg-gray-700'}`}
            title="Settings"
          >
            <Cog6ToothIcon className="w-4 h-4" />
          </button>
          {onExport && (
            <button
              onClick={onExport}
              className="p-1.5 text-gray-400 hover:text-white hover:bg-gray-700 rounded transition-colors"
              title="Export"
            >
              <ArrowDownTrayIcon className="w-4 h-4" />
            </button>
          )}
          {onRefresh && (
            <button
              onClick={onRefresh}
              disabled={isLoading}
              className="p-1.5 text-gray-400 hover:text-white hover:bg-gray-700 rounded transition-colors"
              title="Refresh"
            >
              <ArrowPathIcon className={`w-4 h-4 ${isLoading ? 'animate-spin' : ''}`} />
            </button>
          )}
        </div>
      </div>

      {/* Timeframe Selector */}
      <div className="flex items-center gap-1 mb-3">
        {TIMEFRAMES.map((tf) => (
          <button
            key={tf}
            onClick={() => handleTimeframeChange(tf)}
            className={`px-2 py-1 text-xs rounded transition-colors ${
              timeframe === tf
                ? 'bg-blue-500 text-white'
                : 'bg-gray-700 text-gray-400 hover:text-white'
            }`}
          >
            {tf}
          </button>
        ))}
      </div>

      {/* Settings Panel */}
      {showSettings && (
        <div className="mb-3 p-3 bg-gray-900/50 rounded-lg">
          <div className="grid grid-cols-2 sm:grid-cols-3 gap-3 text-xs">
            <div>
              <label className="text-gray-400 block mb-1">Normalization</label>
              <select
                value={normalization}
                onChange={(e) => setNormalization(e.target.value as NormalizationMode)}
                className="w-full bg-gray-800 border border-gray-700 rounded px-2 py-1 text-white text-xs"
              >
                <option value="percentage">Percentage Change</option>
                <option value="indexed">Indexed (100)</option>
                <option value="absolute">Absolute Price</option>
              </select>
            </div>
            <label className="flex items-center gap-2">
              <input
                type="checkbox"
                checked={showGrid}
                onChange={(e) => setShowGrid(e.target.checked)}
                className="rounded bg-gray-700 border-gray-600"
              />
              <span className="text-gray-300">Show Grid</span>
            </label>
            <label className="flex items-center gap-2">
              <input
                type="checkbox"
                checked={showLegend}
                onChange={(e) => setShowLegend(e.target.checked)}
                className="rounded bg-gray-700 border-gray-600"
              />
              <span className="text-gray-300">Show Legend</span>
            </label>
          </div>
        </div>
      )}

      {/* Symbol Pills */}
      {showLegend && symbols.length > 0 && (
        <div className="flex flex-wrap gap-2 mb-3">
          {symbols.map((symbol) => (
            <div
              key={symbol.symbol}
              className={`flex items-center gap-1.5 px-2 py-1 rounded text-xs transition-opacity ${
                symbol.visible ? 'opacity-100' : 'opacity-50'
              }`}
              style={{ backgroundColor: `${symbol.color}20`, borderColor: symbol.color, borderWidth: 1 }}
            >
              <div className="w-2 h-2 rounded-full" style={{ backgroundColor: symbol.color }} />
              <span className="text-white font-medium">{symbol.symbol}</span>
              <span className={symbol.changePercent >= 0 ? 'text-green-400' : 'text-red-400'}>
                {symbol.changePercent >= 0 ? '+' : ''}{symbol.changePercent.toFixed(2)}%
              </span>
              {onToggleVisibility && (
                <button
                  onClick={() => onToggleVisibility(symbol.symbol)}
                  className="p-0.5 hover:bg-gray-700 rounded"
                >
                  {symbol.visible ? (
                    <EyeIcon className="w-3 h-3 text-gray-400" />
                  ) : (
                    <EyeSlashIcon className="w-3 h-3 text-gray-400" />
                  )}
                </button>
              )}
              {onRemoveSymbol && (
                <button
                  onClick={() => onRemoveSymbol(symbol.symbol)}
                  className="p-0.5 hover:bg-red-500/20 rounded"
                >
                  <XMarkIcon className="w-3 h-3 text-gray-400 hover:text-red-400" />
                </button>
              )}
            </div>
          ))}
        </div>
      )}

      {/* Chart Container */}
      <div ref={containerRef} className="relative flex-1" style={{ minHeight: height }}>
        <canvas
          ref={canvasRef}
          onMouseMove={handleMouseMove}
          onMouseLeave={handleMouseLeave}
          className="w-full cursor-crosshair"
          style={{ height }}
        />

        {/* Tooltip */}
        {hoveredPoint && (
          <div
            className="absolute pointer-events-none bg-gray-900 border border-gray-700 rounded px-3 py-2 text-xs shadow-lg z-10"
            style={{
              left: hoveredPoint.x + 15,
              top: 30,
              transform: hoveredPoint.x > (canvasRef.current?.width || 0) - 150 ? 'translateX(-100%)' : 'none',
            }}
          >
            <div className="text-gray-400 mb-1">
              {new Date(hoveredPoint.timestamp).toLocaleDateString(undefined, {
                weekday: 'short',
                month: 'short',
                day: 'numeric',
                year: 'numeric',
              })}
            </div>
            {hoveredPoint.values.map((v) => (
              <div key={v.symbol} className="flex items-center gap-2">
                <div className="w-2 h-2 rounded-full" style={{ backgroundColor: v.color }} />
                <span className="text-white">{v.symbol}:</span>
                <span style={{ color: v.color }}>
                  {normalization === 'percentage'
                    ? `${v.value >= 0 ? '+' : ''}${v.value.toFixed(2)}%`
                    : v.value.toFixed(2)}
                </span>
              </div>
            ))}
          </div>
        )}

        {/* Loading Overlay */}
        {isLoading && (
          <div className="absolute inset-0 bg-gray-900/50 flex items-center justify-center">
            <ArrowPathIcon className="w-8 h-8 text-cyan-400 animate-spin" />
          </div>
        )}

        {/* Empty State */}
        {!isLoading && symbols.length === 0 && (
          <div className="absolute inset-0 flex items-center justify-center">
            <div className="text-center text-gray-500">
              <ChartBarSquareIcon className="w-12 h-12 mx-auto mb-2 opacity-50" />
              <p className="text-sm">No symbols to compare</p>
              {onAddSymbol && (
                <button
                  onClick={onAddSymbol}
                  className="mt-2 px-3 py-1 bg-blue-500 text-white rounded text-xs hover:bg-blue-600"
                >
                  Add Symbol
                </button>
              )}
            </div>
          </div>
        )}
      </div>
    </div>
  );
};

export default SymbolComparisonChart;
