#!/usr/bin/env node

/**
 * AI Learning Analytics System
 * 
 * Analyzes AI trading performance improvements and generates proof of learning effectiveness
 */

const { PrismaClient } = require('@prisma/client');
const prisma = new PrismaClient();

class AILearningAnalytics {
  constructor() {
    this.startDate = new Date('2025-07-24'); // When AI trading started
  }

  async generateLearningReport() {
    console.log('🧠 AI LEARNING EFFECTIVENESS REPORT');
    console.log('=' .repeat(60));
    console.log('');

    try {
      // Get all learning data since AI started
      const learningData = await this.getLearningData();
      const tradeData = await this.getTradeData();
      const automationSessions = await this.getAutomationSessions();

      // Calculate improvement metrics
      const improvements = await this.calculateImprovements(learningData);
      const pnlAnalysis = await this.calculateTotalPnL(tradeData);
      const accuracyTrends = await this.calculateAccuracyTrends(learningData);
      const confidenceEvolution = await this.calculateConfidenceEvolution(learningData);

      // Generate report
      this.displayOverallStats(learningData, tradeData, automationSessions);
      this.displayLearningImprovements(improvements);
      this.displayPnLAnalysis(pnlAnalysis);
      this.displayAccuracyTrends(accuracyTrends);
      this.displayConfidenceEvolution(confidenceEvolution);

      // Generate JSON for frontend
      const reportData = {
        generated: new Date().toISOString(),
        period: {
          start: this.startDate.toISOString(),
          end: new Date().toISOString(),
          daysActive: Math.ceil((Date.now() - this.startDate.getTime()) / (1000 * 60 * 60 * 24))
        },
        overview: {
          totalLearningRecords: learningData.length,
          totalTrades: tradeData.length,
          totalSessions: automationSessions.length,
          activeSessions: automationSessions.filter(s => s.status === 'ACTIVE').length
        },
        improvements,
        pnl: pnlAnalysis,
        accuracy: accuracyTrends,
        confidence: confidenceEvolution
      };

      // Save report for API
      await this.saveReport(reportData);

      console.log('\n📊 Report saved and ready for dashboard display!');
      return reportData;

    } catch (error) {
      console.error('❌ Error generating learning report:', error.message);
      throw error;
    }
  }

  async getLearningData() {
    return await prisma.aILearningData.findMany({
      where: {
        createdAt: {
          gte: this.startDate
        }
      },
      orderBy: { createdAt: 'asc' }
    });
  }

  async getTradeData() {
    return await prisma.trade.findMany({
      where: {
        createdAt: {
          gte: this.startDate
        },
        isAutomated: true // Only AI trades
      },
      orderBy: { createdAt: 'asc' }
    });
  }

  async getAutomationSessions() {
    return await prisma.automationSession.findMany({
      where: {
        createdAt: {
          gte: this.startDate
        }
      },
      orderBy: { createdAt: 'desc' }
    });
  }

  async calculateImprovements(learningData) {
    if (learningData.length < 10) {
      return {
        improvement: 0,
        trend: 'INSUFFICIENT_DATA',
        message: 'Need more learning data to calculate improvements'
      };
    }

    // Split data into early vs recent periods
    const midPoint = Math.floor(learningData.length / 2);
    const earlyData = learningData.slice(0, midPoint);
    const recentData = learningData.slice(midPoint);

    // Calculate average confidence scores
    const earlyConfidence = this.getAverageConfidence(earlyData);
    const recentConfidence = this.getAverageConfidence(recentData);

    // Calculate accuracy if outcomes are available
    const earlyAccuracy = this.getAccuracy(earlyData);
    const recentAccuracy = this.getAccuracy(recentData);

    const confidenceImprovement = ((recentConfidence - earlyConfidence) / earlyConfidence) * 100;
    const accuracyImprovement = earlyAccuracy && recentAccuracy ? 
      ((recentAccuracy - earlyAccuracy) / earlyAccuracy) * 100 : null;

    return {
      confidenceImprovement: Number(confidenceImprovement.toFixed(2)),
      accuracyImprovement: accuracyImprovement ? Number(accuracyImprovement.toFixed(2)) : null,
      earlyPeriod: {
        samples: earlyData.length,
        avgConfidence: Number(earlyConfidence.toFixed(2)),
        accuracy: earlyAccuracy ? Number(earlyAccuracy.toFixed(2)) : null
      },
      recentPeriod: {
        samples: recentData.length,
        avgConfidence: Number(recentConfidence.toFixed(2)),
        accuracy: recentAccuracy ? Number(recentAccuracy.toFixed(2)) : null
      },
      trend: confidenceImprovement > 5 ? 'IMPROVING' : 
             confidenceImprovement < -5 ? 'DECLINING' : 'STABLE'
    };
  }

  async calculateTotalPnL(tradeData) {
    const analysis = {
      totalTrades: tradeData.length,
      totalPnL: 0,
      totalPnLPercent: 0,
      winningTrades: 0,
      losingTrades: 0,
      breakEvenTrades: 0,
      avgTradeSize: 0,
      bestTrade: null,
      worstTrade: null,
      winRate: 0,
      avgWin: 0,
      avgLoss: 0,
      profitFactor: 0
    };

    if (tradeData.length === 0) {
      return analysis;
    }

    let totalProfit = 0;
    let totalLoss = 0;
    let totalAmount = 0;

    tradeData.forEach(trade => {
      const pnl = trade.profit || 0;
      const pnlPercent = trade.pnlPercent || 0;
      const amount = trade.amount || 0;

      analysis.totalPnL += pnl;
      analysis.totalPnLPercent += pnlPercent;
      totalAmount += amount;

      if (pnl > 0) {
        analysis.winningTrades++;
        totalProfit += pnl;
      } else if (pnl < 0) {
        analysis.losingTrades++;
        totalLoss += Math.abs(pnl);
      } else {
        analysis.breakEvenTrades++;
      }

      // Track best/worst trades
      if (!analysis.bestTrade || pnl > analysis.bestTrade.profit) {
        analysis.bestTrade = trade;
      }
      if (!analysis.worstTrade || pnl < analysis.worstTrade.profit) {
        analysis.worstTrade = trade;
      }
    });

    analysis.avgTradeSize = totalAmount / tradeData.length;
    analysis.winRate = (analysis.winningTrades / tradeData.length) * 100;
    analysis.avgWin = analysis.winningTrades > 0 ? totalProfit / analysis.winningTrades : 0;
    analysis.avgLoss = analysis.losingTrades > 0 ? totalLoss / analysis.losingTrades : 0;
    analysis.profitFactor = analysis.avgLoss > 0 ? analysis.avgWin / analysis.avgLoss : 0;

    // Round numbers
    Object.keys(analysis).forEach(key => {
      if (typeof analysis[key] === 'number') {
        analysis[key] = Number(analysis[key].toFixed(4));
      }
    });

    return analysis;
  }

  async calculateAccuracyTrends(learningData) {
    const trends = [];
    const chunkSize = Math.max(5, Math.floor(learningData.length / 10)); // At least 5 samples per chunk

    for (let i = 0; i < learningData.length; i += chunkSize) {
      const chunk = learningData.slice(i, i + chunkSize);
      const accuracy = this.getAccuracy(chunk);
      const confidence = this.getAverageConfidence(chunk);
      
      trends.push({
        period: i / chunkSize + 1,
        samples: chunk.length,
        accuracy: accuracy ? Number(accuracy.toFixed(2)) : null,
        confidence: Number(confidence.toFixed(2)),
        timestamp: chunk[chunk.length - 1]?.createdAt
      });
    }

    return trends;
  }

  async calculateConfidenceEvolution(learningData) {
    return learningData.map((record, index) => ({
      index: index + 1,
      timestamp: record.createdAt,
      confidence: record.confidenceScore || 0,
      accuracy: record.accuracyScore || null,
      symbol: record.symbol,
      outcome: record.outcome
    }));
  }

  getAverageConfidence(data) {
    const confidenceScores = data
      .map(d => d.confidenceScore || d.analysisData?.confidence || 0.5)
      .filter(score => score > 0);
    
    return confidenceScores.length > 0 ? 
      confidenceScores.reduce((a, b) => a + b, 0) / confidenceScores.length : 0.5;
  }

  getAccuracy(data) {
    const withOutcomes = data.filter(d => d.outcome && d.accuracyScore);
    if (withOutcomes.length === 0) return null;

    const avgAccuracy = withOutcomes.reduce((sum, d) => sum + (d.accuracyScore || 0), 0) / withOutcomes.length;
    return avgAccuracy;
  }

  displayOverallStats(learningData, tradeData, automationSessions) {
    console.log('📈 OVERALL AI TRADING STATISTICS');
    console.log(`   Period: ${this.startDate.toDateString()} - ${new Date().toDateString()}`);
    console.log(`   Learning Records: ${learningData.length}`);
    console.log(`   AI Trades Executed: ${tradeData.length}`);
    console.log(`   Automation Sessions: ${automationSessions.length}`);
    console.log(`   Active Sessions: ${automationSessions.filter(s => s.status === 'ACTIVE').length}`);
    console.log('');
  }

  displayLearningImprovements(improvements) {
    console.log('🧠 AI LEARNING IMPROVEMENTS');
    if (improvements.trend === 'INSUFFICIENT_DATA') {
      console.log(`   ⚠️ ${improvements.message}`);
    } else {
      console.log(`   📊 Confidence Improvement: ${improvements.confidenceImprovement > 0 ? '+' : ''}${improvements.confidenceImprovement}%`);
      if (improvements.accuracyImprovement !== null) {
        console.log(`   🎯 Accuracy Improvement: ${improvements.accuracyImprovement > 0 ? '+' : ''}${improvements.accuracyImprovement}%`);
      }
      console.log(`   📈 Trend: ${improvements.trend}`);
      console.log(`   Early Period: ${improvements.earlyPeriod.avgConfidence}% confidence (${improvements.earlyPeriod.samples} samples)`);
      console.log(`   Recent Period: ${improvements.recentPeriod.avgConfidence}% confidence (${improvements.recentPeriod.samples} samples)`);
    }
    console.log('');
  }

  displayPnLAnalysis(pnl) {
    console.log('💰 TOTAL PnL ANALYSIS');
    console.log(`   Total Trades: ${pnl.totalTrades}`);
    console.log(`   Total PnL: $${pnl.totalPnL.toFixed(4)}`);
    console.log(`   Total PnL %: ${pnl.totalPnLPercent.toFixed(2)}%`);
    console.log(`   Win Rate: ${pnl.winRate.toFixed(1)}%`);
    console.log(`   Winning Trades: ${pnl.winningTrades}`);
    console.log(`   Losing Trades: ${pnl.losingTrades}`);
    console.log(`   Break Even: ${pnl.breakEvenTrades}`);
    if (pnl.totalTrades > 0) {
      console.log(`   Average Trade Size: $${pnl.avgTradeSize.toFixed(2)}`);
      console.log(`   Average Win: $${pnl.avgWin.toFixed(4)}`);
      console.log(`   Average Loss: $${pnl.avgLoss.toFixed(4)}`);
      console.log(`   Profit Factor: ${pnl.profitFactor.toFixed(2)}`);
    }
    console.log('');
  }

  displayAccuracyTrends(trends) {
    console.log('📊 ACCURACY TRENDS OVER TIME');
    trends.forEach(trend => {
      console.log(`   Period ${trend.period}: ${trend.confidence}% confidence, ${trend.accuracy ? trend.accuracy + '% accuracy' : 'no accuracy data'} (${trend.samples} samples)`);
    });
    console.log('');
  }

  displayConfidenceEvolution(evolution) {
    console.log('📈 RECENT CONFIDENCE EVOLUTION');
    const recentData = evolution.slice(-10); // Last 10 records
    recentData.forEach(record => {
      const date = new Date(record.timestamp).toLocaleDateString();
      console.log(`   ${date}: ${(record.confidence * 100).toFixed(1)}% confidence (${record.symbol})`);
    });
    console.log('');
  }

  async saveReport(reportData) {
    const fs = require('fs');
    const reportPath = './public/ai-learning-report.json';
    
    // Ensure public directory exists
    if (!fs.existsSync('./public')) {
      fs.mkdirSync('./public', { recursive: true });
    }
    
    fs.writeFileSync(reportPath, JSON.stringify(reportData, null, 2));
    console.log(`📁 Report saved to: ${reportPath}`);
  }
}

// Run the analytics
async function main() {
  const analytics = new AILearningAnalytics();
  try {
    await analytics.generateLearningReport();
  } catch (error) {
    console.error('Failed to generate report:', error);
  } finally {
    await prisma.$disconnect();
  }
}

if (require.main === module) {
  main();
}

module.exports = AILearningAnalytics;
