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

interface IndicatorsComparisonProps {
  backtests: Backtest[]
}

const IndicatorsComparison: React.FC<IndicatorsComparisonProps> = ({ backtests }) => {
  const theme = useTheme().themeProperty();
  
  // 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;
  };

  // Filter backtests to only include successful ones
  const validBacktests = backtests.filter(b => b.statistics)
  
  if (validBacktests.length === 0) {
    return (
      <div className="card bg-base-100 shadow-xl">
        <div className="card-body">
          <h3 className="card-title">Strategy Comparison</h3>
          <p className="text-center text-gray-500">No valid results to display</p>
        </div>
      </div>
    )
  }

  // Group results by indicator type and calculate average metrics
  const indicatorStats = new Map<string, {
    type: string
    count: number
    totalPnl: number
    totalWinRate: number
    totalScore: number
    totalFitness: number
    totalDrawdown: number
    bestFitness: number
    bestPnl: number
    bestWinRate: number
    bestScore: number
    bestSharpe: number
    bestHodlPnl: number
    bestPnlVsHodl: number
    bestNumPositions: number
    bestMaxDrawdown: number
    avgDrawdown: number
    generation: number
  }>()

  validBacktests.forEach(backtest => {
    if (!backtest.config.scenario?.indicators) return;
    
    backtest.config.scenario.indicators.forEach((indicator: any) => {
      const key = indicator.type?.toString() || 'Unknown';
      const existing = indicatorStats.get(key);
             const sharpe = backtest.statistics?.sharpeRatio ?? 0;
       const pnl = backtest.statistics?.totalPnL ?? 0;
       // Calculate PnL vs HODL using the hodlPercentage from backtest
       const hodlPnl = (backtest.hodlPercentage / 100) * (backtest.config.botTradingBalance || 10000);
       const pnlVsHodl = pnl - hodlPnl;
      const numPositions = backtest.positions?.length ?? 0;
      const avgDrawdown = Math.abs(backtest.statistics?.maxDrawdownPc ?? 0);
      const fitness = calculateFitnessScore(backtest);
      const generation = getGeneration(backtest);
      
      if (existing) {
        existing.count++;
        existing.totalPnl += pnl;
        existing.totalWinRate += backtest.winRate || 0;
        existing.totalScore += backtest.score || 0;
        existing.totalFitness += fitness;
        existing.totalDrawdown += avgDrawdown;
        
        // Track best performance
        if (fitness > existing.bestFitness) {
          existing.bestFitness = fitness;
          existing.bestPnl = pnl;
          existing.bestWinRate = backtest.winRate || 0;
          existing.bestScore = backtest.score || 0;
          existing.bestSharpe = sharpe;
          existing.bestHodlPnl = hodlPnl;
          existing.bestPnlVsHodl = pnlVsHodl;
          existing.bestNumPositions = numPositions;
          existing.bestMaxDrawdown = avgDrawdown;
          existing.avgDrawdown = existing.totalDrawdown / existing.count;
          existing.generation = generation;
        }
      } else {
        indicatorStats.set(key, {
          type: key,
          count: 1,
          totalPnl: pnl,
          totalWinRate: backtest.winRate || 0,
          totalScore: backtest.score || 0,
          totalFitness: fitness,
          totalDrawdown: avgDrawdown,
          bestFitness: fitness,
          bestPnl: pnl,
          bestWinRate: backtest.winRate || 0,
          bestScore: backtest.score || 0,
          bestSharpe: sharpe,
          bestHodlPnl: hodlPnl,
          bestPnlVsHodl: pnlVsHodl,
          bestNumPositions: numPositions,
          bestMaxDrawdown: avgDrawdown,
          avgDrawdown: avgDrawdown,
          generation: generation,
        })
      }
    })
  })

  // Convert to array and calculate averages
  const indicatorData = Array.from(indicatorStats.values()).map(stat => ({
    ...stat,
    avgPnl: stat.totalPnl / stat.count,
    avgWinRate: stat.totalWinRate / stat.count,
    avgScore: stat.totalScore / stat.count,
    avgFitness: stat.totalFitness / stat.count,
    avgDrawdown: stat.totalDrawdown / stat.count,
  }))

  // Sort by best fitness score
  const sortedIndicators = indicatorData.sort((a, b) => b.bestFitness - a.bestFitness)

  // Find max values for normalization
  const maxPnl = Math.max(...sortedIndicators.map(d => Math.abs(d.bestPnl))) || 1
  const maxWinRate = Math.max(...sortedIndicators.map(d => d.bestWinRate)) || 1
  const maxScore = Math.max(...sortedIndicators.map(d => Math.abs(d.bestScore))) || 1
  const maxFitness = Math.max(...sortedIndicators.map(d => d.bestFitness)) || 1
  const maxSharpe = Math.max(...sortedIndicators.map(d => Math.abs(d.bestSharpe))) || 1
  const maxPnlVsHodl = Math.max(...sortedIndicators.map(d => Math.abs(d.bestPnlVsHodl))) || 1
  const maxNumPositions = Math.max(...sortedIndicators.map(d => d.bestNumPositions)) || 1
  const maxAvgDrawdown = Math.max(...sortedIndicators.map(d => d.avgDrawdown)) || 1

  // Normalize values between 0 and 1
  const normalizedIndicators = sortedIndicators.map(d => ({
    ...d,
    normPnl: d.bestPnl / maxPnl,
    normWinRate: d.bestWinRate / maxWinRate,
    normScore: d.bestScore / maxScore,
    normFitness: d.bestFitness / maxFitness,
    normSharpe: d.bestSharpe / maxSharpe,
    normPnlVsHodl: d.bestPnlVsHodl / maxPnlVsHodl,
    normNumPositions: d.bestNumPositions / maxNumPositions,
    normAvgDrawdown: d.avgDrawdown / maxAvgDrawdown,
  }))

  // Create stacked bar chart data (normalized)
  const barData = [
    {
      type: 'bar' as const,
      x: normalizedIndicators.map(d => d.type),
      y: normalizedIndicators.map(d => d.normPnl),
      name: 'PnL',
      marker: {
        color: '#FF6B6B',
        opacity: 0.8
      },
      hovertemplate: 
        '<b>%{x}</b><br>' +
        '<b>PnL (raw):</b> $%{customdata[0]:.2f}<br>' +
        '<b>Normalized:</b> %{y:.2f}<br>' +
        '<b>Count:</b> %{customdata[1]}<br>' +
        '<b>Best Gen:</b> %{customdata[2]}<br>' +
        '<extra></extra>',
      customdata: normalizedIndicators.map(d => [d.bestPnl, d.count, d.generation])
    },
    {
      type: 'bar' as const,
      x: normalizedIndicators.map(d => d.type),
      y: normalizedIndicators.map(d => d.normWinRate),
      name: 'Win Rate',
      marker: {
        color: '#4ECDC4',
        opacity: 0.8
      },
      hovertemplate: 
        '<b>%{x}</b><br>' +
        '<b>Win Rate (raw):</b> %{customdata[0]:.1f}%<br>' +
        '<b>Normalized:</b> %{y:.2f}<br>' +
        '<b>Count:</b> %{customdata[1]}<br>' +
        '<b>Best Gen:</b> %{customdata[2]}<br>' +
        '<extra></extra>',
      customdata: normalizedIndicators.map(d => [d.bestWinRate, d.count, d.generation])
    },
    {
      type: 'bar' as const,
      x: normalizedIndicators.map(d => d.type),
      y: normalizedIndicators.map(d => d.normScore),
      name: 'Score',
      marker: {
        color: '#45B7D1',
        opacity: 0.8
      },
      hovertemplate: 
        '<b>%{x}</b><br>' +
        '<b>Score (raw):</b> %{customdata[0]:.2f}<br>' +
        '<b>Normalized:</b> %{y:.2f}<br>' +
        '<b>Count:</b> %{customdata[1]}<br>' +
        '<b>Best Gen:</b> %{customdata[2]}<br>' +
        '<extra></extra>',
      customdata: normalizedIndicators.map(d => [d.bestScore, d.count, d.generation])
    },
    {
      type: 'bar' as const,
      x: normalizedIndicators.map(d => d.type),
      y: normalizedIndicators.map(d => d.normFitness),
      name: 'Fitness',
      marker: {
        color: '#96CEB4',
        opacity: 0.8
      },
      hovertemplate: 
        '<b>%{x}</b><br>' +
        '<b>Fitness (raw):</b> %{customdata[0]:.3f}<br>' +
        '<b>Normalized:</b> %{y:.2f}<br>' +
        '<b>Count:</b> %{customdata[1]}<br>' +
        '<b>Best Gen:</b> %{customdata[2]}<br>' +
        '<extra></extra>',
      customdata: normalizedIndicators.map(d => [d.bestFitness, d.count, d.generation])
    },
    {
      type: 'bar' as const,
      x: normalizedIndicators.map(d => d.type),
      y: normalizedIndicators.map(d => d.normSharpe),
      name: 'Sharpe Ratio',
      marker: {
        color: '#FFD700',
        opacity: 0.8
      },
      hovertemplate: 
        '<b>%{x}</b><br>' +
        '<b>Sharpe Ratio (raw):</b> %{customdata[0]:.3f}<br>' +
        '<b>Normalized:</b> %{y:.2f}<br>' +
        '<b>Count:</b> %{customdata[1]}<br>' +
        '<b>Best Gen:</b> %{customdata[2]}<br>' +
        '<extra></extra>',
      customdata: normalizedIndicators.map(d => [d.bestSharpe, d.count, d.generation])
    },
    {
      type: 'bar' as const,
      x: normalizedIndicators.map(d => d.type),
      y: normalizedIndicators.map(d => d.normPnlVsHodl),
      name: 'PnL vs HODL',
      marker: {
        color: '#FF8C42',
        opacity: 0.8
      },
      hovertemplate: 
        '<b>%{x}</b><br>' +
        '<b>PnL vs HODL (raw):</b> $%{customdata[0]:.2f}<br>' +
        '<b>Normalized:</b> %{y:.2f}<br>' +
        '<b>Count:</b> %{customdata[1]}<br>' +
        '<b>Best Gen:</b> %{customdata[2]}<br>' +
        '<extra></extra>',
      customdata: normalizedIndicators.map(d => [d.bestPnlVsHodl, d.count, d.generation])
    },
    {
      type: 'bar' as const,
      x: normalizedIndicators.map(d => d.type),
      y: normalizedIndicators.map(d => d.normNumPositions),
      name: 'Trade Count',
      marker: {
        color: '#9B59B6',
        opacity: 0.8
      },
      hovertemplate: 
        '<b>%{x}</b><br>' +
        '<b>Trade Count (raw):</b> %{customdata[0]}<br>' +
        '<b>Normalized:</b> %{y:.2f}<br>' +
        '<b>Count:</b> %{customdata[1]}<br>' +
        '<b>Best Gen:</b> %{customdata[2]}<br>' +
        '<extra></extra>',
      customdata: normalizedIndicators.map(d => [d.bestNumPositions, d.count, d.generation])
    },
    {
      type: 'bar' as const,
      x: normalizedIndicators.map(d => d.type),
      y: normalizedIndicators.map(d => d.normAvgDrawdown),
      name: 'Avg Drawdown',
      marker: {
        color: '#E74C3C',
        opacity: 0.8
      },
      hovertemplate: 
        '<b>%{x}</b><br>' +
        '<b>Avg Drawdown (raw):</b> %{customdata[0]:.1f}%<br>' +
        '<b>Normalized:</b> %{y:.2f}<br>' +
        '<b>Count:</b> %{customdata[1]}<br>' +
        '<b>Best Gen:</b> %{customdata[2]}<br>' +
        '<extra></extra>',
      customdata: normalizedIndicators.map(d => [d.avgDrawdown, d.count, d.generation])
    }
  ]

  return (
    <div className="card bg-base-100 shadow-xl">
      <div className="card-body">
        <h3 className="card-title">Indicator Performance Comparison</h3>
        <div className="text-sm text-gray-500 mb-4">
          Stacked bar chart showing <b>normalized</b> performance metrics (0-1) for each indicator type. 
          Each bar represents the best performance achieved by that indicator across all generations.
        </div>
        
        <Plot
          data={barData}
          layout={{
            title: { 
              text: 'Indicator Performance by Metrics (Normalized 0-1)',
              font: { color: '#ffffff' }
            },
            barmode: 'stack' as const,
            xaxis: {
              title: { 
                text: 'Indicator Type',
                font: { color: '#ffffff' }
              },
              tickfont: { color: '#ffffff' },
              gridcolor: '#374151',
            },
            yaxis: {
              title: { 
                text: 'Normalized Performance (0-1)',
                font: { color: '#ffffff' }
              },
              tickfont: { color: '#ffffff' },
              gridcolor: '#374151',
              rangemode: 'tozero' as const, // y-axis starts at zero
              autorange: true,
              range: [0, 1]
            },
            showlegend: true,
            legend: {
              font: { color: '#ffffff' },
              bgcolor: 'rgba(0,0,0,0)',
              bordercolor: 'rgba(0,0,0,0)'
            },
            paper_bgcolor: theme['base-100'],
            plot_bgcolor: theme['base-100'],
            width: 1200,
            height: 600,
            margin: {
              b: 100, // Extra space for x-axis labels
              l: 80,
              pad: 0,
              r: 50,
              t: 80,
            },
          }}
          config={{ displayModeBar: false }}
        />
        
        {/* Detailed indicator table */}
        <div className="mt-6">
          <h4 className="text-lg font-semibold mb-4">Detailed Performance Summary</h4>
          <div className="overflow-x-auto">
            <table className="table table-zebra w-full">
              <thead>
                <tr>
                  <th>Indicator</th>
                  <th>Count</th>
                  <th>Best PnL</th>
                  <th>Best Win Rate</th>
                  <th>Best Score</th>
                  <th>Best Fitness</th>
                  <th>Best Sharpe</th>
                  <th>Best Gen</th>
                </tr>
              </thead>
              <tbody>
                {sortedIndicators.map((indicator, index) => (
                  <tr key={indicator.type}>
                    <td className="font-medium">{indicator.type}</td>
                    <td>{indicator.count}</td>
                    <td className={indicator.bestPnl >= 0 ? 'text-success' : 'text-error'}>
                      ${indicator.bestPnl.toFixed(2)}
                    </td>
                    <td>{indicator.bestWinRate.toFixed(1)}%</td>
                    <td>{indicator.bestScore.toFixed(2)}</td>
                    <td>{indicator.bestFitness.toFixed(3)}</td>
                    <td className={indicator.bestSharpe >= 0 ? 'text-success' : 'text-error'}>
                      {indicator.bestSharpe.toFixed(3)}
                    </td>
                    <td>{indicator.generation}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>
      </div>
    </div>
  )
}

export default IndicatorsComparison
