import * as LightweightCharts from 'lightweight-charts';
import { useEffect, useRef, useCallback } from 'react';

export interface ChartData {
  time: number;
  open?: number;
  high?: number;
  low?: number;
  close?: number;
  value?: number;
  volume?: number;
}

export interface ChartProps {
  data: ChartData[];
  height?: number;
  type?: 'candlestick' | 'line' | 'area';
  showVolume?: boolean;
  theme?: 'light' | 'dark';
  overlayData?: Array<{
    name: string;
    data: Array<{ time: number; value: number }>;
    color?: string;
    lineWidth?: number;
  }>;
  className?: string;
}

export function Chart({
  data,
  height = 400,
  type = 'candlestick',
  showVolume = true,
  theme = 'dark',
  overlayData = [],
  className = '',
}: ChartProps) {
  const chartContainerRef = useRef<HTMLDivElement>(null);
  const chartRef = useRef<LightweightCharts.IChartApi | null>(null);
  const mainSeriesRef = useRef<LightweightCharts.ISeriesApi<any> | null>(null);
  const volumeSeriesRef = useRef<LightweightCharts.ISeriesApi<any> | null>(null);
  const overlaySeriesRef = useRef<Map<string, LightweightCharts.ISeriesApi<any>>>(new Map());
  
  // Reset zoom handler
  const resetZoom = useCallback(() => {
    if (chartRef.current) {
      chartRef.current.timeScale().fitContent();
    }
  }, []);

  useEffect(() => {
    if (!chartContainerRef.current || !data || !data.length) {
      return;
    }

    // Create chart
    const chart = LightweightCharts.createChart(chartContainerRef.current, {
      width: chartContainerRef.current.clientWidth,
      height: height,
      layout: {
        background: { 
          type: LightweightCharts.ColorType.Solid, 
          color: theme === 'dark' ? '#0f0f0f' : '#ffffff' 
        },
        textColor: theme === 'dark' ? '#d1d5db' : '#374151',
      },
      grid: {
        vertLines: {
          color: theme === 'dark' ? '#1f2937' : '#e5e7eb',
          visible: true,
        },
        horzLines: {
          color: theme === 'dark' ? '#1f2937' : '#e5e7eb',
          visible: true,
        },
      },
      crosshair: {
        mode: LightweightCharts.CrosshairMode.Normal,
      },
      rightPriceScale: {
        borderColor: theme === 'dark' ? '#1f2937' : '#e5e7eb',
        autoScale: true,
      },
      timeScale: {
        borderColor: theme === 'dark' ? '#1f2937' : '#e5e7eb',
        timeVisible: true,
        secondsVisible: false,
        rightOffset: 12,
        barSpacing: 3,
        fixLeftEdge: true,
        fixRightEdge: true,
      },
    });

    chartRef.current = chart;

    // Filter and validate data
    const validateAndFilterData = (rawData: any[]) => {
      const seen = new Set<number>();
      return rawData.filter((item, index) => {
        if (seen.has(item.time)) {
          return false;
        }
        seen.add(item.time);
        return true;
      });
    };

    // Create main series
    if (type === 'candlestick' && data[0].open !== undefined) {
      mainSeriesRef.current = chart.addCandlestickSeries({
        upColor: '#10b981',
        downColor: '#ef4444',
        borderUpColor: '#10b981',
        borderDownColor: '#ef4444',
        wickUpColor: '#10b981',
        wickDownColor: '#ef4444',
      });
      const validData = validateAndFilterData(data);
      mainSeriesRef.current.setData(validData as LightweightCharts.CandlestickData[]);
    } else if (type === 'line' || (type === 'candlestick' && data[0].value !== undefined)) {
      mainSeriesRef.current = chart.addLineSeries({
        color: '#3b82f6',
        lineWidth: 2,
      });
      const lineData = data.map(d => ({
        time: d.time,
        value: d.value ?? d.close ?? 0
      }));
      const validData = validateAndFilterData(lineData);
      mainSeriesRef.current.setData(validData);
    } else if (type === 'area') {
      mainSeriesRef.current = chart.addAreaSeries({
        lineColor: '#3b82f6',
        topColor: '#3b82f6',
        bottomColor: 'rgba(59, 130, 246, 0.1)',
        lineWidth: 2,
      });
      const areaData = data.map(d => ({
        time: d.time,
        value: d.value ?? d.close ?? 0
      }));
      const validData = validateAndFilterData(areaData);
      mainSeriesRef.current.setData(validData);
    }

    // Add volume if available
    if (showVolume && data.some(d => d.volume)) {
      volumeSeriesRef.current = chart.addHistogramSeries({
        color: '#3b82f680',
        priceFormat: {
          type: 'volume',
        },
        priceScaleId: 'volume',
      });
      
      volumeSeriesRef.current.priceScale().applyOptions({
        scaleMargins: {
          top: 0.8,
          bottom: 0,
        },
      });

      const volumeData = data
        .filter(d => d.volume !== undefined)
        .map(d => ({
          time: d.time,
          value: d.volume!,
          color: d.close && d.open ? 
            (d.close >= d.open ? '#10b98140' : '#ef444440') : 
            '#3b82f640',
        }));
      volumeSeriesRef.current.setData(volumeData);
    }

    // Add overlay series
    overlaySeriesRef.current.clear();
    overlayData.forEach((overlay, index) => {
      const series = chart.addLineSeries({
        color: overlay.color || ['#ff9800', '#4caf50', '#9c27b0', '#f44336'][index % 4],
        lineWidth: overlay.lineWidth || 2,
        title: overlay.name,
        priceScaleId: index === 0 ? '' : `overlay-${index}`, // First overlay uses main scale
      });
      
      if (index > 0) {
        series.priceScale().applyOptions({
          scaleMargins: {
            top: 0.1,
            bottom: 0.1,
          },
        });
      }
      
      // Filter out duplicate timestamps and ensure ascending order
      const uniqueData = overlay.data.reduce((acc: any[], curr) => {
        if (!acc.length || curr.time > acc[acc.length - 1].time) {
          acc.push(curr);
        }
        return acc;
      }, []);
      series.setData(uniqueData);
      overlaySeriesRef.current.set(overlay.name, series);
    });

    // Fit content with a slight delay to ensure all series are loaded
    setTimeout(() => {
      chart.timeScale().fitContent();
      
      // Also set the visible range to ensure all data is shown
      if (data.length > 0) {
        const firstTime = data[0].time;
        const lastTime = data[data.length - 1].time;
        chart.timeScale().setVisibleRange({
          from: firstTime as any,
          to: lastTime as any,
        });
      }
    }, 100);
    
    // Enable mouse wheel zoom and touch gestures
    chart.applyOptions({
      handleScroll: {
        mouseWheel: true,
        pressedMouseMove: true,
        horzTouchDrag: true,
        vertTouchDrag: true,
      },
      handleScale: {
        mouseWheel: true,
        pinch: true,
        axisPressedMouseMove: true,
      },
    });

    // Handle resize
    const handleResize = () => {
      if (chartContainerRef.current && chart) {
        chart.applyOptions({
          width: chartContainerRef.current.clientWidth,
        });
      }
    };

    window.addEventListener('resize', handleResize);

    // Cleanup
    return () => {
      window.removeEventListener('resize', handleResize);
      if (chart) {
        chart.remove();
      }
    };
  }, [data, height, type, showVolume, theme, overlayData]);

  return (
    <div className={`relative ${className}`}>
      <div 
        ref={chartContainerRef} 
        style={{ width: '100%', height: `${height}px` }}
      />
      <button
        onClick={resetZoom}
        className="absolute top-2 right-2 px-2 py-1 text-xs bg-surface-primary border border-border rounded hover:bg-surface-secondary transition-colors"
        title="Reset zoom"
      >
        Reset Zoom
      </button>
    </div>
  );
}