import { Agent } from './Agent';
import { LearningSystem, LEARNING_COURSES } from './LearningSystem';
import { RiskManager } from './RiskManager';
import { FactorSystem, AVAILABLE_FACTORS } from './FactorSystem';
import { MemorySystem } from './MemorySystem';

export class TradingTeam {
  agents: Record<string, Agent> = {};
  learningSystem = new LearningSystem();
  riskManager = new RiskManager();
  factorSystem = new FactorSystem();
  memorySystem = new MemorySystem();
  
  constructor() {
    this.agents = {
      market_analyst: new Agent('market_analyst', 'market', 0.05, 1000),
      sentiment_analyst: new Agent('sentiment_analyst', 'sentiment', 0.08, 1000),
      fundamental_analyst: new Agent('fundamental_analyst', 'fundamental', 0.10, 1000),
      bull_researcher: new Agent('bull_researcher', 'bull', 0.15, 2000),
      bear_researcher: new Agent('bear_researcher', 'bear', 0.15, 2000),
      risk_manager: new Agent('risk_manager', 'risk', 0.20, 3000),
      trader: new Agent('trader', 'trader', 0.30, 10000)
    };
  }

  simulateCycle(symbol: string, currentTime: number, marketTrend: number, onLog: (msg: string) => void) {
    const activities: Record<string, string> = {};
    
    // Update learning
    Object.values(this.agents).forEach(agent => {
      this.learningSystem.updateLearning(agent, currentTime);
    });

    // Decide activity
    for (const [name, agent] of Object.entries(this.agents)) {
      const status = agent.economicTracker.getSurvivalStatus();
      if (status === '💀 bankrupt') {
        activities[name] = 'liquidate';
        continue;
      }
      
      if (status === '🔴 critical') {
        activities[name] = (agent.winRate > 0.7 && agent.skillLevel > 0.8) ? 'conservative_trade' : 'paper_trade';
      } else if (status === '⚠️ struggling') {
        activities[name] = agent.winRate < 0.5 ? 'learn' : 'selective_trade';
      } else if (status === '💪 stable') {
        activities[name] = agent.skillLevel < 0.6 ? 'learn' : 'normal_trade';
      } else {
        activities[name] = agent.skillLevel < 0.9 ? 'aggressive_learn' : 'aggressive_trade';
      }
    }

    // Execute learning and buying factors
    for (const [name, activity] of Object.entries(activities)) {
      const agent = this.agents[name];
      if (activity.includes('learn')) {
        if (!agent.learningStatus) {
          const courses = Object.keys(LEARNING_COURSES) as (keyof typeof LEARNING_COURSES)[];
          const course = courses[Math.floor(Math.random() * courses.length)];
          const enrolled = this.learningSystem.enrollCourse(agent, course, currentTime);
          if (enrolled) {
            onLog(`📚 ${name} enrolled in ${course} for $${LEARNING_COURSES[course].cost}`);
          }
        }
      }
      
      // Randomly try to buy a factor if thriving
      if (agent.economicTracker.getSurvivalStatus() === '🚀 thriving' && Math.random() < 0.2) {
        const factors = Object.keys(AVAILABLE_FACTORS) as (keyof typeof AVAILABLE_FACTORS)[];
        const factor = factors[Math.floor(Math.random() * factors.length)];
        if (!agent.unlockedFactors.includes(factor)) {
          const bought = this.factorSystem.purchaseFactor(agent, factor);
          if (bought) {
            onLog(`🧩 ${name} purchased factor ${factor} for $${AVAILABLE_FACTORS[factor].cost}`);
          }
        }
      }
    }

    // Analysis Phase
    let marketScore = 0;
    let analysisCost = 0;
    
    ['market_analyst', 'sentiment_analyst', 'fundamental_analyst'].forEach(name => {
      const analyst = this.agents[name];
      if (['normal_trade', 'selective_trade', 'conservative_trade', 'aggressive_trade'].includes(activities[name])) {
        const cost = analyst.economicTracker.calculateDecisionCost(2000, 500, 5);
        analysisCost += cost;
        // Analysts are more accurate if they have higher skill level
        const accuracy = analyst.skillLevel;
        const score = marketTrend * accuracy + (Math.random() * 2 - 1) * (1 - accuracy);
        marketScore += score;
        onLog(`🔍 ${name} analyzed ${symbol} (Score: ${score.toFixed(2)}), cost: $${cost.toFixed(4)}`);
      }
    });

    // Debate Phase
    let confidence = 0.5;
    ['bull_researcher', 'bear_researcher'].forEach(name => {
      const researcher = this.agents[name];
      if (['normal_trade', 'selective_trade', 'aggressive_trade'].includes(activities[name])) {
        const cost = researcher.economicTracker.calculateDecisionCost(3000, 1000, 2);
        
        // Bull tends to be positive, Bear tends to be negative, accuracy depends on skill
        const bias = name === 'bull_researcher' ? 0.5 : -0.5;
        const view = (marketTrend * researcher.skillLevel) + bias * (1 - researcher.skillLevel) + (Math.random() * 0.4 - 0.2);
        
        confidence += view * 0.5;
        onLog(`🗣️ ${name} debated on ${symbol} (View: ${view.toFixed(2)}), cost: $${cost.toFixed(4)}`);
      }
    });

    // UMP Referee System (from abu)
    const failureRate = this.memorySystem.getFailureRate(symbol);
    let umpBlocked = false;
    if (failureRate > 0.6) {
        umpBlocked = true;
        onLog(`🛑 UMP Referee blocked trade for ${symbol} due to high recent failure rate (${(failureRate*100).toFixed(0)}%)`);
    }

    // Risk & Trade
    const trader = this.agents['trader'];
    if (!umpBlocked && ['normal_trade', 'selective_trade', 'conservative_trade', 'aggressive_trade'].includes(activities['trader'])) {
      // Use memory to adjust win rate
      const historicalWinRate = this.memorySystem.getRecentWinRate(symbol);
      const baseWinRate = trader.winRate + trader.getWinRateModifier();
      
      // Combine trader's base win rate, historical win rate, and the team's market analysis score
      const teamSignalStrength = Math.max(0, Math.min(1, (marketScore + confidence) / 3 + 0.5));
      const adjustedWinRate = baseWinRate * 0.5 + historicalWinRate * 0.2 + teamSignalStrength * 0.3;
      
      const isWin = Math.random() < adjustedWinRate;
      const baseValue = trader.economicTracker.balance * 0.1; 
      const tradeSignal = { positionSize: baseValue, stopLoss: 0.05 };
      
      const approval = this.riskManager.evaluateTradeRisk(trader, tradeSignal);
      
      if (approval.approved) {
        const actualPosition = approval.maxPositionSize;
        const pnlPercent = isWin ? (Math.random() * 0.1 + 0.02) : -(Math.random() * 0.05 + 0.01) * trader.getRiskModifier();
        const pnlAmount = actualPosition * pnlPercent;
        
        const result = trader.economicTracker.calculateTradeCost(
          actualPosition, 
          isWin, 
          isWin ? pnlAmount : 0, 
          !isWin ? -pnlAmount : 0
        );
        
        // Save to memory
        this.memorySystem.addRecord({
          id: Math.random().toString(36).substring(7),
          symbol,
          tradeSignal,
          result: { pnl: result.pnl, isWin, fee: result.fee },
          timestamp: currentTime
        });
        
        onLog(`💰 Trader executed ${symbol} trade. PNL: $${result.pnl.toFixed(2)}, Fee: $${result.fee.toFixed(2)}. Status: ${result.status}`);
      } else {
        onLog(`🛡️ Risk Manager blocked trade for ${symbol}: ${approval.reason}`);
      }
    }
  }
}
