/**
 * TradingChart Component
 * Professional trading chart using lightweight-charts
 */

import React, { useEffect, useRef, useState, useCallback } from 'react';
import {
  createChart,
  IChartApi,
  ISeriesApi,
  CandlestickData,
  HistogramData,
  Time,
  ColorType,
  CrosshairMode,
  LineStyle,
} from 'lightweight-charts';

// ============================================================================
// Types
// ============================================================================

export type Interval = '1m' | '5m' | '15m' | '30m' | '1h' | '4h' | '1d' | '1w';

interface Candle {
  time: number;
  open: number;
  high: number;
  low: number;
  close: number;
  volume: number;
}

interface TradingChartProps {
  symbol: string;
  interval?: Interval;
  height?: number;
  theme?: 'dark' | 'light';
  showVolume?: boolean;
  showToolbar?: boolean;
  onIntervalChange?: (interval: Interval) => void;
  onCrosshairMove?: (data: { time: Time; price: number } | null) => void;
}

interface ChartTheme {
  backgroundColor: string;
  textColor: string;
  gridColor: string;
  upColor: string;
  downColor: string;
  borderUpColor: string;
  borderDownColor: string;
  wickUpColor: string;
  wickDownColor: string;
  volumeUpColor: string;
  volumeDownColor: string;
}

// ============================================================================
// Constants
// ============================================================================

const INTERVALS: { value: Interval; label: string }[] = [
  { value: '1m', label: '1m' },
  { value: '5m', label: '5m' },
  { value: '15m', label: '15m' },
  { value: '30m', label: '30m' },
  { value: '1h', label: '1H' },
  { value: '4h', label: '4H' },
  { value: '1d', label: '1D' },
  { value: '1w', label: '1W' },
];

const THEMES: Record<'dark' | 'light', ChartTheme> = {
  dark: {
    backgroundColor: '#1a1a2e',
    textColor: '#d1d4dc',
    gridColor: '#2B2B43',
    upColor: '#26a69a',
    downColor: '#ef5350',
    borderUpColor: '#26a69a',
    borderDownColor: '#ef5350',
    wickUpColor: '#26a69a',
    wickDownColor: '#ef5350',
    volumeUpColor: 'rgba(38, 166, 154, 0.5)',
    volumeDownColor: 'rgba(239, 83, 80, 0.5)',
  },
  light: {
    backgroundColor: '#ffffff',
    textColor: '#131722',
    gridColor: '#e1e1e1',
    upColor: '#26a69a',
    downColor: '#ef5350',
    borderUpColor: '#26a69a',
    borderDownColor: '#ef5350',
    wickUpColor: '#26a69a',
    wickDownColor: '#ef5350',
    volumeUpColor: 'rgba(38, 166, 154, 0.5)',
    volumeDownColor: 'rgba(239, 83, 80, 0.5)',
  },
};

// ============================================================================
// API Functions
// ============================================================================

async function fetchKlines(symbol: string, interval: Interval, limit: number = 500): Promise<Candle[]> {
  const response = await fetch(
    `/api/v1/trading/market/klines/${symbol}?interval=${interval}&limit=${limit}`
  );

  if (!response.ok) {
    throw new Error('Failed to fetch klines');
  }

  const data = await response.json();
  return data.data;
}

// ============================================================================
// Subcomponents
// ============================================================================

interface TimeframeSelectorProps {
  value: Interval;
  onChange: (interval: Interval) => void;
  theme: 'dark' | 'light';
}

const TimeframeSelector: React.FC<TimeframeSelectorProps> = ({ value, onChange, theme }) => {
  const bgColor = theme === 'dark' ? 'bg-gray-800' : 'bg-gray-100';
  const activeColor = theme === 'dark' ? 'bg-blue-600 text-white' : 'bg-blue-500 text-white';
  const inactiveColor = theme === 'dark' ? 'text-gray-400 hover:text-white' : 'text-gray-600 hover:text-black';

  return (
    <div className={`flex gap-1 ${bgColor} rounded-lg p-1`}>
      {INTERVALS.map((interval) => (
        <button
          key={interval.value}
          onClick={() => onChange(interval.value)}
          className={`px-3 py-1 text-sm font-medium rounded transition-colors ${
            value === interval.value ? activeColor : inactiveColor
          }`}
        >
          {interval.label}
        </button>
      ))}
    </div>
  );
};

interface PriceDisplayProps {
  symbol: string;
  currentPrice: number | null;
  priceChange: number | null;
  priceChangePercent: number | null;
  theme: 'dark' | 'light';
}

const PriceDisplay: React.FC<PriceDisplayProps> = ({
  symbol,
  currentPrice,
  priceChange,
  priceChangePercent,
  theme,
}) => {
  const textColor = theme === 'dark' ? 'text-white' : 'text-gray-900';
  const isPositive = (priceChange || 0) >= 0;
  const changeColor = isPositive ? 'text-green-500' : 'text-red-500';

  return (
    <div className="flex items-center gap-4">
      <span className={`text-lg font-bold ${textColor}`}>{symbol}</span>
      {currentPrice !== null && (
        <>
          <span className={`text-xl font-mono ${textColor}`}>
            {currentPrice.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 8 })}
          </span>
          {priceChange !== null && priceChangePercent !== null && (
            <span className={`text-sm font-medium ${changeColor}`}>
              {isPositive ? '+' : ''}
              {priceChange.toFixed(2)} ({isPositive ? '+' : ''}
              {priceChangePercent.toFixed(2)}%)
            </span>
          )}
        </>
      )}
    </div>
  );
};

// ============================================================================
// Main Component
// ============================================================================

export const TradingChart: React.FC<TradingChartProps> = ({
  symbol,
  interval: initialInterval = '1h',
  height = 500,
  theme = 'dark',
  showVolume = true,
  showToolbar = true,
  onIntervalChange,
  onCrosshairMove,
}) => {
  const containerRef = useRef<HTMLDivElement>(null);
  const chartRef = useRef<IChartApi | null>(null);
  const candleSeriesRef = useRef<ISeriesApi<'Candlestick'> | null>(null);
  const volumeSeriesRef = useRef<ISeriesApi<'Histogram'> | null>(null);

  const [interval, setInterval] = useState<Interval>(initialInterval);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [currentPrice, setCurrentPrice] = useState<number | null>(null);
  const [priceChange, setPriceChange] = useState<number | null>(null);
  const [priceChangePercent, setPriceChangePercent] = useState<number | null>(null);

  const chartTheme = THEMES[theme];

  // Initialize chart
  useEffect(() => {
    if (!containerRef.current) return;

    const chart = createChart(containerRef.current, {
      width: containerRef.current.clientWidth,
      height: height - (showToolbar ? 50 : 0),
      layout: {
        background: { type: ColorType.Solid, color: chartTheme.backgroundColor },
        textColor: chartTheme.textColor,
      },
      grid: {
        vertLines: { color: chartTheme.gridColor },
        horzLines: { color: chartTheme.gridColor },
      },
      crosshair: {
        mode: CrosshairMode.Normal,
        vertLine: {
          width: 1,
          color: 'rgba(224, 227, 235, 0.4)',
          style: LineStyle.Solid,
          labelBackgroundColor: chartTheme.backgroundColor,
        },
        horzLine: {
          width: 1,
          color: 'rgba(224, 227, 235, 0.4)',
          style: LineStyle.Solid,
          labelBackgroundColor: chartTheme.backgroundColor,
        },
      },
      rightPriceScale: {
        borderColor: chartTheme.gridColor,
      },
      timeScale: {
        borderColor: chartTheme.gridColor,
        timeVisible: true,
        secondsVisible: false,
      },
    });

    // Add candlestick series
    const candleSeries = chart.addCandlestickSeries({
      upColor: chartTheme.upColor,
      downColor: chartTheme.downColor,
      borderUpColor: chartTheme.borderUpColor,
      borderDownColor: chartTheme.borderDownColor,
      wickUpColor: chartTheme.wickUpColor,
      wickDownColor: chartTheme.wickDownColor,
    });

    // Add volume series
    let volumeSeries: ISeriesApi<'Histogram'> | null = null;
    if (showVolume) {
      volumeSeries = chart.addHistogramSeries({
        color: chartTheme.volumeUpColor,
        priceFormat: {
          type: 'volume',
        },
        priceScaleId: '',
      });
      volumeSeries.priceScale().applyOptions({
        scaleMargins: {
          top: 0.8,
          bottom: 0,
        },
      });
    }

    // Handle crosshair movement
    chart.subscribeCrosshairMove((param) => {
      if (!param || !param.time || !param.seriesData) {
        onCrosshairMove?.(null);
        return;
      }

      const candleData = param.seriesData.get(candleSeries) as CandlestickData;
      if (candleData) {
        onCrosshairMove?.({
          time: param.time,
          price: candleData.close as number,
        });
      }
    });

    chartRef.current = chart;
    candleSeriesRef.current = candleSeries;
    volumeSeriesRef.current = volumeSeries;

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

    window.addEventListener('resize', handleResize);

    return () => {
      window.removeEventListener('resize', handleResize);
      chart.remove();
    };
  }, [height, showVolume, chartTheme, onCrosshairMove, showToolbar]);

  // Load data
  const loadData = useCallback(async () => {
    if (!candleSeriesRef.current) return;

    setLoading(true);
    setError(null);

    try {
      const candles = await fetchKlines(symbol, interval);

      if (candles.length === 0) {
        setError('No data available');
        return;
      }

      // Transform data for candlestick series
      const candleData: CandlestickData[] = candles.map((c) => ({
        time: (c.time / 1000) as Time,
        open: c.open,
        high: c.high,
        low: c.low,
        close: c.close,
      }));

      candleSeriesRef.current.setData(candleData);

      // Transform data for volume series
      if (volumeSeriesRef.current && showVolume) {
        const volumeData: HistogramData[] = candles.map((c) => ({
          time: (c.time / 1000) as Time,
          value: c.volume,
          color: c.close >= c.open ? chartTheme.volumeUpColor : chartTheme.volumeDownColor,
        }));
        volumeSeriesRef.current.setData(volumeData);
      }

      // Update price info
      const lastCandle = candles[candles.length - 1];
      const firstCandle = candles[0];
      setCurrentPrice(lastCandle.close);
      setPriceChange(lastCandle.close - firstCandle.open);
      setPriceChangePercent(((lastCandle.close - firstCandle.open) / firstCandle.open) * 100);

      // Fit content
      chartRef.current?.timeScale().fitContent();
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to load chart data');
    } finally {
      setLoading(false);
    }
  }, [symbol, interval, showVolume, chartTheme]);

  useEffect(() => {
    loadData();
  }, [loadData]);

  // Handle interval change
  const handleIntervalChange = (newInterval: Interval) => {
    setInterval(newInterval);
    onIntervalChange?.(newInterval);
  };

  return (
    <div className="flex flex-col" style={{ height }}>
      {/* Toolbar */}
      {showToolbar && (
        <div
          className={`flex items-center justify-between px-4 py-2 ${
            theme === 'dark' ? 'bg-gray-900' : 'bg-gray-50'
          } border-b ${theme === 'dark' ? 'border-gray-700' : 'border-gray-200'}`}
        >
          <PriceDisplay
            symbol={symbol}
            currentPrice={currentPrice}
            priceChange={priceChange}
            priceChangePercent={priceChangePercent}
            theme={theme}
          />
          <TimeframeSelector value={interval} onChange={handleIntervalChange} theme={theme} />
        </div>
      )}

      {/* Chart Container */}
      <div className="relative flex-1">
        <div ref={containerRef} className="w-full h-full" />

        {/* Loading Overlay */}
        {loading && (
          <div className="absolute inset-0 flex items-center justify-center bg-black/50">
            <div className="flex items-center gap-2 text-white">
              <svg
                className="animate-spin h-5 w-5"
                xmlns="http://www.w3.org/2000/svg"
                fill="none"
                viewBox="0 0 24 24"
              >
                <circle
                  className="opacity-25"
                  cx="12"
                  cy="12"
                  r="10"
                  stroke="currentColor"
                  strokeWidth="4"
                />
                <path
                  className="opacity-75"
                  fill="currentColor"
                  d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
                />
              </svg>
              <span>Loading chart...</span>
            </div>
          </div>
        )}

        {/* Error Overlay */}
        {error && !loading && (
          <div className="absolute inset-0 flex items-center justify-center bg-black/50">
            <div className="text-center text-white">
              <p className="text-red-400 mb-2">{error}</p>
              <button
                onClick={loadData}
                className="px-4 py-2 bg-blue-600 rounded-lg hover:bg-blue-700 transition-colors"
              >
                Retry
              </button>
            </div>
          </div>
        )}
      </div>
    </div>
  );
};

export default TradingChart;
