import React from 'react';
import Plot from 'react-plotly.js';
import {Backtest} from '../../../generated/ManagingApi';
import useTheme from '../../../hooks/useTheme';

interface Fitness3DPlotProps {
  backtests: Backtest[];
  theme: { secondary: string };
}

const Fitness3DPlot: React.FC<Fitness3DPlotProps> = ({ backtests }) => {
    const theme = useTheme().themeProperty()

  const LOOPBACK_CONFIG = {
    singleIndicator: 1,
    multipleIndicators: { min: 5, max: 15 },
  };

  // Helper function to calculate fitness score from backtest data
  const calculateFitnessScore = (backtest: Backtest): number => {
    if (!backtest.statistics) return 0;
    
    const stats = backtest.statistics;
    
    // Multi-objective fitness function (matching the backend calculation)
    const pnlScore = Math.max(0, (stats.totalPnL || 0) / 1000); // Normalize PnL
    const winRateScore = (backtest.winRate || 0) / 100; // Normalize win rate
    const riskRewardScore = Math.min(2, (stats.winningTrades || 0) / Math.max(1, Math.abs(stats.loosingTrades || 1)));
    const consistencyScore = 1 - Math.abs((stats.totalPnL || 0) - (backtest.finalPnl || 0)) / Math.max(1, Math.abs(stats.totalPnL || 1));
    
    // Risk-reward ratio bonus
    const riskRewardRatio = (backtest.config.moneyManagement?.takeProfit || 0) / (backtest.config.moneyManagement?.stopLoss || 1);
    const riskRewardBonus = Math.min(0.2, (riskRewardRatio - 1.1) * 0.1);
    
    // Drawdown score (normalized to 0-1, where lower drawdown is better)
    const maxDrawdownPc = Math.abs(stats.maxDrawdownPc || 0);
    const drawdownScore = Math.max(0, 1 - (maxDrawdownPc / 50));
    
    // Weighted combination
    const fitness = 
      pnlScore * 0.3 + 
      winRateScore * 0.2 + 
      riskRewardScore * 0.2 + 
      consistencyScore * 0.1 +
      riskRewardBonus * 0.1 +
      drawdownScore * 0.1;
    
    return Math.max(0, fitness);
  };

  // Helper function to get generation from metadata
  const getGeneration = (backtest: Backtest): number => {
    if (backtest.metadata && typeof backtest.metadata === 'object' && 'generation' in backtest.metadata) {
      return (backtest.metadata as any).generation || 0;
    }
    return 0;
  };

  // Helper function to get indicator details from config
  const getIndicatorDetails = (backtest: Backtest): string => {
    if (!backtest.config.scenario?.indicators) return 'Unknown';
    
    return backtest.config.scenario.indicators.map((indicator: any) => {
      let details = indicator.type?.toString() || 'Unknown';
      if (indicator.period) details += ` (${indicator.period})`;
      if (indicator.fastPeriods && indicator.slowPeriods) details += ` (${indicator.fastPeriods}/${indicator.slowPeriods})`;
      if (indicator.multiplier) details += ` (${indicator.multiplier.toFixed(1)}x)`;
      return details;
    }).join(', ');
  };

  const plotData = backtests.length > 0 ? [
    {
      type: 'scatter3d' as const,
      mode: 'markers' as const,
      x: backtests.map(b => calculateFitnessScore(b)),
      y: backtests.map(b => b.score || 0),
      z: backtests.map(b => b.winRate || 0),
      marker: {
        size: 5,
        color: backtests.map(b => getGeneration(b)),
        colorscale: 'Viridis' as const,
        opacity: 0.8,
      },
      text: backtests.map(b => {
        const generation = getGeneration(b);
        const fitness = calculateFitnessScore(b);
        const indicatorDetails = getIndicatorDetails(b);
        const riskRewardRatio = (b.config.moneyManagement?.takeProfit || 0) / (b.config.moneyManagement?.stopLoss || 1);
        const riskRewardColor = riskRewardRatio >= 2 ? '🟢' : riskRewardRatio >= 1.5 ? '🟡' : '🔴';
        const maxDrawdownPc = Math.abs(b.statistics?.maxDrawdownPc || 0);
        const drawdownColor = maxDrawdownPc <= 10 ? '🟢' : maxDrawdownPc <= 25 ? '🟡' : '🔴';
        
        return `Generation: ${generation}<br>` +
               `Fitness: ${fitness.toFixed(2)}<br>` +
               `PnL: $${b.statistics?.totalPnL?.toFixed(2) || 'N/A'}<br>` +
               `Win Rate: ${b.winRate?.toFixed(1) || 'N/A'}%<br>` +
               `Max Drawdown: ${drawdownColor} ${maxDrawdownPc.toFixed(1)}%<br>` +
               `SL: ${b.config.moneyManagement?.stopLoss?.toFixed(1) || 'N/A'}%<br>` +
               `TP: ${b.config.moneyManagement?.takeProfit?.toFixed(1) || 'N/A'}%<br>` +
               `R/R: ${riskRewardColor} ${riskRewardRatio.toFixed(2)}<br>` +
               `Leverage: ${b.config.moneyManagement?.leverage || 1}x<br>` +
               `Cooldown: ${b.config.cooldownPeriod || 0} candles<br>` +
               `Max Loss Streak: ${b.config.maxLossStreak || 0}<br>` +
               `Max Time: ${b.config.maxPositionTimeHours || 0}h<br>` +
               `Indicators: ${indicatorDetails}<br>` +
               `Loopback: ${b.config.scenario?.loopbackPeriod || 'Unknown'}`;
      }),
      hovertemplate: '%{text}<extra></extra>',
    },
  ] : [];

  return (
    <Plot
      data={plotData}
      layout={{
        title: {text: 'Fitness Score vs Score vs Win Rate'},
        scene: {
          xaxis: {title: {text: 'Fitness Score'}, zerolinecolor: theme.secondary, color: theme.secondary},
          yaxis: {title: {text: 'Score'}, zerolinecolor: theme.secondary, color: theme.secondary},
          zaxis: {title: {text: 'Win Rate (%)'}, zerolinecolor: theme.secondary, color: theme.secondary},
        },
        width: 750,
        height: 600,
        margin: {
          b: 20,
          l: 0,
          pad: 0,
          r: 0,
          t: 0,
        },
        paper_bgcolor: "rgba(0,0,0,0)",
        plot_bgcolor: "rgba(0,0,0,0)",
      }}
      config={{displayModeBar: false}}
    />
  );
};

export default Fitness3DPlot; 