import { IServiceContainer } from '@stock-bot/di';
import { TradingEngine } from '@stock-bot/engine';
import { EventEmitter } from 'events';
import { ExecutionService } from '../services/ExecutionService';
import { MarketDataService } from '../services/MarketDataService';
import { StorageService } from '../services/StorageService';
import { BacktestConfigSchema, LiveConfigSchema, ModeConfig, PaperConfigSchema, TradingMode } from '../types';

export class ModeManager extends EventEmitter {
  private mode: TradingMode = 'paper';
  private config: ModeConfig | null = null;
  private tradingEngine: TradingEngine | null = null;
  private isInitialized = false;
  private container: IServiceContainer;

  constructor(
    container: IServiceContainer,
    private marketDataService: MarketDataService,
    private executionService: ExecutionService,
    private storageService: StorageService
  ) {
    super();
    this.container = container;
  }

  async initializeMode(config: ModeConfig): Promise<void> {
    // Validate config based on mode
    switch (config.mode) {
      case 'backtest':
        BacktestConfigSchema.parse(config);
        break;
      case 'paper':
        PaperConfigSchema.parse(config);
        break;
      case 'live':
        LiveConfigSchema.parse(config);
        break;
    }

    // Shutdown current mode if initialized
    if (this.isInitialized) {
      await this.shutdown();
    }

    this.mode = config.mode;
    this.config = config;

    // Create Rust trading engine with appropriate config
    const engineConfig = this.createEngineConfig(config);
    this.tradingEngine = new TradingEngine(config.mode, engineConfig);

    // Initialize services for the mode
    await this.initializeServices(config);

    this.isInitialized = true;
    this.emit('modeChanged', config);
    
    this.container.logger.info(`Trading mode initialized: ${config.mode}`);
  }

  private createEngineConfig(config: ModeConfig): any {
    switch (config.mode) {
      case 'backtest':
        return {
          startTime: new Date(config.startDate).getTime(),
          endTime: new Date(config.endDate).getTime(),
          speedMultiplier: this.getSpeedMultiplier(config.speed),
          initialCapital: config.initialCapital
        };
      case 'paper':
        return {
          startingCapital: config.startingCapital
        };
      case 'live':
        return {
          broker: config.broker,
          accountId: config.accountId
        };
    }
  }

  private getSpeedMultiplier(speed: string): number {
    switch (speed) {
      case 'max': return 0;
      case 'realtime': return 1;
      case '2x': return 2;
      case '5x': return 5;
      case '10x': return 10;
      default: return 0;
    }
  }

  private async initializeServices(config: ModeConfig): Promise<void> {
    // Configure market data service
    await this.marketDataService.initialize(config);
    
    // Configure execution service
    await this.executionService.initialize(config, this.tradingEngine!);
    
    // Configure storage
    await this.storageService.initialize(config);
  }

  getCurrentMode(): TradingMode {
    return this.mode;
  }

  getConfig(): ModeConfig | null {
    return this.config;
  }

  getTradingEngine(): TradingEngine {
    if (!this.tradingEngine) {
      throw new Error('Trading engine not initialized');
    }
    return this.tradingEngine;
  }

  isBacktestMode(): boolean {
    return this.mode === 'backtest';
  }

  isPaperMode(): boolean {
    return this.mode === 'paper';
  }

  isLiveMode(): boolean {
    return this.mode === 'live';
  }

  async transitionMode(fromMode: TradingMode, toMode: TradingMode, config: ModeConfig): Promise<void> {
    if (fromMode === 'paper' && toMode === 'live') {
      // Special handling for paper to live transition
      this.container.logger.info('Transitioning from paper to live trading...');
      
      // 1. Get current paper positions
      const paperPositions = await this.tradingEngine!.getOpenPositions();
      
      // 2. Initialize new mode
      await this.initializeMode(config);
      
      // 3. Reconcile positions (this would be handled by a reconciliation service)
      this.container.logger.info(`Paper positions to reconcile: ${paperPositions}`);
    } else {
      // Standard mode switch
      await this.initializeMode(config);
    }
  }

  async shutdown(): Promise<void> {
    if (!this.isInitialized) {return;}

    this.container.logger.info(`Shutting down ${this.mode} mode...`);
    
    // Shutdown services
    await this.marketDataService.shutdown();
    await this.executionService.shutdown();
    await this.storageService.shutdown();
    
    // Cleanup trading engine
    this.tradingEngine = null;
    this.isInitialized = false;
    
    this.emit('shutdown');
  }
}