/**
 * Prediction Chart Component
 * Displays candlestick chart with ML predictions overlay
 */

import React, { useMemo } from 'react';
import {
  ComposedChart,
  Area,
  Line,
  XAxis,
  YAxis,
  CartesianGrid,
  Tooltip,
  ResponsiveContainer,
  ReferenceLine,
  Scatter,
} from 'recharts';
import type { OHLCVCandle, PredictionPoint, TradeSignal } from '../../../services/backtestService';

interface PredictionChartProps {
  candles: OHLCVCandle[];
  predictions: PredictionPoint[];
  signals: TradeSignal[];
  showPredictions?: boolean;
  showSignals?: boolean;
  showVolume?: boolean;
  height?: number;
  className?: string;
}

interface ChartDataPoint {
  timestamp: string;
  date: string;
  open: number;
  high: number;
  low: number;
  close: number;
  volume: number;
  predicted_high?: number;
  predicted_low?: number;
  actual_high?: number;
  actual_low?: number;
  signal_buy?: number;
  signal_sell?: number;
  confidence?: number;
}

export const PredictionChart: React.FC<PredictionChartProps> = ({
  candles,
  predictions,
  signals,
  showPredictions = true,
  showSignals = true,
  showVolume = false,
  height = 500,
  className = '',
}) => {
  // Merge candles with predictions and signals
  const chartData = useMemo(() => {
    const predictionMap = new Map(
      predictions.map((p) => [p.timestamp.slice(0, 16), p])
    );
    const signalMap = new Map(
      signals.map((s) => [s.timestamp.slice(0, 16), s])
    );

    return candles.map((candle): ChartDataPoint => {
      const timestamp = candle.timestamp.slice(0, 16);
      const prediction = predictionMap.get(timestamp);
      const signal = signalMap.get(timestamp);

      const baseClose = candle.close;

      return {
        timestamp: candle.timestamp,
        date: new Date(candle.timestamp).toLocaleDateString(),
        open: candle.open,
        high: candle.high,
        low: candle.low,
        close: candle.close,
        volume: candle.volume,
        // Predicted range as absolute prices
        predicted_high: prediction
          ? baseClose * (1 + prediction.delta_high_predicted / 100)
          : undefined,
        predicted_low: prediction
          ? baseClose * (1 - Math.abs(prediction.delta_low_predicted) / 100)
          : undefined,
        actual_high: prediction ? candle.high : undefined,
        actual_low: prediction ? candle.low : undefined,
        // Signal markers
        signal_buy: signal?.direction === 'buy' ? signal.price : undefined,
        signal_sell: signal?.direction === 'sell' ? signal.price : undefined,
        confidence: prediction?.confidence_high,
      };
    });
  }, [candles, predictions, signals]);

  // Calculate price range for Y axis
  const { minPrice, maxPrice } = useMemo(() => {
    let min = Infinity;
    let max = -Infinity;

    chartData.forEach((d) => {
      min = Math.min(min, d.low, d.predicted_low || Infinity);
      max = Math.max(max, d.high, d.predicted_high || -Infinity);
    });

    const padding = (max - min) * 0.05;
    return { minPrice: min - padding, maxPrice: max + padding };
  }, [chartData]);

  // Custom tooltip
  const CustomTooltip = ({ active, payload, label }: any) => {
    if (!active || !payload || !payload.length) return null;

    const data = payload[0].payload as ChartDataPoint;

    return (
      <div className="bg-gray-900 border border-gray-700 rounded-lg p-3 shadow-lg">
        <p className="text-xs text-gray-400 mb-2">
          {new Date(data.timestamp).toLocaleString()}
        </p>
        <div className="grid grid-cols-2 gap-x-4 gap-y-1 text-xs">
          <span className="text-gray-400">Open:</span>
          <span className="text-white">{data.open.toFixed(5)}</span>
          <span className="text-gray-400">High:</span>
          <span className="text-green-400">{data.high.toFixed(5)}</span>
          <span className="text-gray-400">Low:</span>
          <span className="text-red-400">{data.low.toFixed(5)}</span>
          <span className="text-gray-400">Close:</span>
          <span className="text-white">{data.close.toFixed(5)}</span>
        </div>
        {data.predicted_high && (
          <div className="mt-2 pt-2 border-t border-gray-700">
            <p className="text-xs text-purple-400 font-semibold mb-1">Predictions</p>
            <div className="grid grid-cols-2 gap-x-4 gap-y-1 text-xs">
              <span className="text-gray-400">Pred High:</span>
              <span className="text-purple-300">{data.predicted_high.toFixed(5)}</span>
              <span className="text-gray-400">Pred Low:</span>
              <span className="text-purple-300">{data.predicted_low?.toFixed(5)}</span>
              {data.confidence && (
                <>
                  <span className="text-gray-400">Confidence:</span>
                  <span className="text-yellow-400">{(data.confidence * 100).toFixed(1)}%</span>
                </>
              )}
            </div>
          </div>
        )}
        {(data.signal_buy || data.signal_sell) && (
          <div className="mt-2 pt-2 border-t border-gray-700">
            <p className={`text-xs font-semibold ${data.signal_buy ? 'text-green-400' : 'text-red-400'}`}>
              {data.signal_buy ? '🔼 BUY Signal' : '🔽 SELL Signal'}
            </p>
          </div>
        )}
      </div>
    );
  };

  // Simplified candlestick using bars
  const CandlestickBar = (props: any) => {
    const { x, y, width, payload } = props;
    const isUp = payload.close >= payload.open;
    const color = isUp ? '#22c55e' : '#ef4444';

    const barWidth = Math.max(width * 0.8, 2);
    const wickWidth = 1;

    // Calculate positions
    const bodyTop = Math.min(payload.open, payload.close);
    const bodyBottom = Math.max(payload.open, payload.close);

    // Scale to chart coordinates (this is approximate - real implementation would need proper scaling)
    const priceRange = maxPrice - minPrice;
    const chartHeight = 400; // Approximate
    const scale = (price: number) => ((maxPrice - price) / priceRange) * chartHeight;

    return (
      <g>
        {/* Wick */}
        <line
          x1={x + width / 2}
          y1={scale(payload.high) + 50}
          x2={x + width / 2}
          y2={scale(payload.low) + 50}
          stroke={color}
          strokeWidth={wickWidth}
        />
        {/* Body */}
        <rect
          x={x + (width - barWidth) / 2}
          y={scale(bodyBottom) + 50}
          width={barWidth}
          height={Math.max(Math.abs(scale(bodyTop) - scale(bodyBottom)), 1)}
          fill={isUp ? 'transparent' : color}
          stroke={color}
          strokeWidth={1}
        />
      </g>
    );
  };

  return (
    <div className={`bg-gray-900 border border-gray-800 rounded-xl p-4 ${className}`}>
      <div className="flex items-center justify-between mb-4">
        <h3 className="text-lg font-bold text-white">Price Chart with Predictions</h3>
        <div className="flex items-center gap-4 text-xs">
          {showPredictions && (
            <div className="flex items-center gap-1">
              <div className="w-3 h-3 bg-purple-500/30 border border-purple-500 rounded" />
              <span className="text-gray-400">Predicted Range</span>
            </div>
          )}
          {showSignals && (
            <>
              <div className="flex items-center gap-1">
                <div className="w-3 h-3 bg-green-500 rounded-full" />
                <span className="text-gray-400">Buy Signal</span>
              </div>
              <div className="flex items-center gap-1">
                <div className="w-3 h-3 bg-red-500 rounded-full" />
                <span className="text-gray-400">Sell Signal</span>
              </div>
            </>
          )}
        </div>
      </div>

      <ResponsiveContainer width="100%" height={height}>
        <ComposedChart data={chartData} margin={{ top: 10, right: 30, left: 10, bottom: 10 }}>
          <CartesianGrid strokeDasharray="3 3" stroke="#374151" />
          <XAxis
            dataKey="timestamp"
            tickFormatter={(value: string) => new Date(value).toLocaleDateString()}
            stroke="#6b7280"
            tick={{ fontSize: 10 }}
            interval="preserveStartEnd"
          />
          <YAxis
            domain={[minPrice, maxPrice]}
            stroke="#6b7280"
            tick={{ fontSize: 10 }}
            tickFormatter={(value: number) => value.toFixed(4)}
          />
          <Tooltip content={<CustomTooltip />} />

          {/* Predicted range area */}
          {showPredictions && (
            <Area
              type="monotone"
              dataKey="predicted_high"
              stroke="#a855f7"
              fill="#a855f7"
              fillOpacity={0.1}
              strokeWidth={1}
              strokeDasharray="5 5"
              dot={false}
              connectNulls
            />
          )}
          {showPredictions && (
            <Area
              type="monotone"
              dataKey="predicted_low"
              stroke="#a855f7"
              fill="#a855f7"
              fillOpacity={0.1}
              strokeWidth={1}
              strokeDasharray="5 5"
              dot={false}
              connectNulls
            />
          )}

          {/* Actual price lines */}
          <Line
            type="monotone"
            dataKey="high"
            stroke="#22c55e"
            strokeWidth={1}
            dot={false}
          />
          <Line
            type="monotone"
            dataKey="low"
            stroke="#ef4444"
            strokeWidth={1}
            dot={false}
          />
          <Line
            type="monotone"
            dataKey="close"
            stroke="#ffffff"
            strokeWidth={2}
            dot={false}
          />

          {/* Buy signals */}
          {showSignals && (
            <Scatter
              dataKey="signal_buy"
              fill="#22c55e"
              shape="triangle"
            />
          )}

          {/* Sell signals */}
          {showSignals && (
            <Scatter
              dataKey="signal_sell"
              fill="#ef4444"
              shape="triangle"
            />
          )}
        </ComposedChart>
      </ResponsiveContainer>

      {/* Legend */}
      <div className="mt-4 flex items-center justify-center gap-6 text-xs">
        <div className="flex items-center gap-1">
          <div className="w-8 h-0.5 bg-white" />
          <span className="text-gray-400">Close</span>
        </div>
        <div className="flex items-center gap-1">
          <div className="w-8 h-0.5 bg-green-500" />
          <span className="text-gray-400">High</span>
        </div>
        <div className="flex items-center gap-1">
          <div className="w-8 h-0.5 bg-red-500" />
          <span className="text-gray-400">Low</span>
        </div>
        <div className="flex items-center gap-1">
          <div className="w-8 h-0.5 bg-purple-500 border-dashed" style={{ borderStyle: 'dashed' }} />
          <span className="text-gray-400">Predicted</span>
        </div>
      </div>
    </div>
  );
};

export default PredictionChart;
