import { BaseStrategy, Signal } from '../BaseStrategy';
import { MarketData } from '../../types';
import { getLogger } from '@stock-bot/logger';

const logger = getLogger('SimpleMovingAverageCrossover');

export class SimpleMovingAverageCrossover extends BaseStrategy {
  private priceHistory = new Map<string, number[]>();
  private positions = new Map<string, number>();
  private lastSignalTime = new Map<string, number>();
  private totalSignals = 0;
  
  // Strategy parameters
  private readonly FAST_PERIOD = 10;
  private readonly SLOW_PERIOD = 20;
  private readonly POSITION_SIZE = 0.1; // 10% of capital per position
  private readonly MIN_SIGNAL_INTERVAL = 24 * 60 * 60 * 1000; // 1 day minimum between signals
  
  constructor(config: any, modeManager?: any, executionService?: any) {
    super(config, modeManager, executionService);
    logger.info(`SimpleMovingAverageCrossover initialized with Fast=${this.FAST_PERIOD}, Slow=${this.SLOW_PERIOD}`);
  }
  
  protected updateIndicators(data: MarketData): void {
    if (data.type !== 'bar') return;
    
    const symbol = data.data.symbol;
    const price = data.data.close;
    
    // Update price history
    if (!this.priceHistory.has(symbol)) {
      this.priceHistory.set(symbol, []);
      logger.info(`📊 Starting to track ${symbol} @ ${price}`);
    }
    
    const history = this.priceHistory.get(symbol)!;
    history.push(price);
    
    // Keep only needed history
    if (history.length > this.SLOW_PERIOD * 2) {
      history.shift();
    }
    
    // Log when we have enough data to start trading
    if (history.length === this.SLOW_PERIOD) {
      logger.info(`✅ ${symbol} now has enough history (${history.length} bars) to start trading`);
    }
  }

  protected async generateSignal(data: MarketData): Promise<Signal | null> {
    if (data.type !== 'bar') return null;
    
    const symbol = data.data.symbol;
    const history = this.priceHistory.get(symbol);
    
    if (!history || history.length < this.SLOW_PERIOD) {
      if (history && history.length % 5 === 0) {
        logger.debug(`${symbol} - Not enough history: ${history.length}/${this.SLOW_PERIOD} bars`);
      }
      return null;
    }
    
    // Calculate moving averages
    const fastMA = this.calculateSMA(history, this.FAST_PERIOD);
    const slowMA = this.calculateSMA(history, this.SLOW_PERIOD);
    
    // Get previous MAs for crossover detection
    const prevHistory = history.slice(0, -1);
    const prevFastMA = this.calculateSMA(prevHistory, this.FAST_PERIOD);
    const prevSlowMA = this.calculateSMA(prevHistory, this.SLOW_PERIOD);
    
    const currentPosition = this.positions.get(symbol) || 0;
    const currentPrice = data.data.close;
    const timestamp = new Date(data.data.timestamp).toISOString().split('T')[0];
    
    // Log every 50 bars to track MA values and crossover conditions
    if (history.length % 50 === 0) {
      logger.info(`${symbol} @ ${timestamp} - Price: ${currentPrice.toFixed(2)}, Fast MA: ${fastMA.toFixed(2)}, Slow MA: ${slowMA.toFixed(2)}, Position: ${currentPosition}`);
      logger.debug(`${symbol} - Prev Fast MA: ${prevFastMA.toFixed(2)}, Prev Slow MA: ${prevSlowMA.toFixed(2)}`);
      logger.debug(`${symbol} - Fast > Slow: ${fastMA > slowMA}, Prev Fast <= Prev Slow: ${prevFastMA <= prevSlowMA}`);
    }
    
    // Detect crossovers with detailed logging
    const goldenCross = prevFastMA <= prevSlowMA && fastMA > slowMA;
    const deathCross = prevFastMA >= prevSlowMA && fastMA < slowMA;
    
    if (goldenCross && currentPosition === 0) {
      // Golden cross - buy signal
      logger.info(`🟢 Golden cross detected for ${symbol} @ ${timestamp}`);
      logger.info(`   Price: ${currentPrice.toFixed(2)}, Fast MA: ${fastMA.toFixed(2)} > Slow MA: ${slowMA.toFixed(2)}`);
      logger.info(`   Prev Fast MA: ${prevFastMA.toFixed(2)} <= Prev Slow MA: ${prevSlowMA.toFixed(2)}`);
      
      // Calculate position size
      const positionSize = this.calculatePositionSize(currentPrice);
      logger.info(`   Position size: ${positionSize} shares`);
      
      const signal: Signal = {
        type: 'buy',
        symbol,
        strength: 0.8,
        reason: 'Golden cross - Fast MA crossed above Slow MA',
        metadata: {
          fastMA,
          slowMA,
          prevFastMA,
          prevSlowMA,
          crossoverType: 'golden',
          price: currentPrice,
          quantity: positionSize
        }
      };
      
      // Track signal time
      this.lastSignalTime.set(symbol, Date.now());
      this.totalSignals++;
      logger.info(`👉 Total signals generated: ${this.totalSignals}`);
      
      return signal;
    } else if (deathCross && currentPosition > 0) {
      // Death cross - sell signal
      logger.info(`🔴 Death cross detected for ${symbol} @ ${timestamp}`);
      logger.info(`   Price: ${currentPrice.toFixed(2)}, Fast MA: ${fastMA.toFixed(2)} < Slow MA: ${slowMA.toFixed(2)}`);
      logger.info(`   Prev Fast MA: ${prevFastMA.toFixed(2)} >= Prev Slow MA: ${prevSlowMA.toFixed(2)}`);
      logger.info(`   Current position: ${currentPosition} shares`);
      
      const signal: Signal = {
        type: 'sell',
        symbol,
        strength: 0.8,
        reason: 'Death cross - Fast MA crossed below Slow MA',
        metadata: {
          fastMA,
          slowMA,
          prevFastMA,
          prevSlowMA,
          crossoverType: 'death',
          price: currentPrice,
          quantity: currentPosition
        }
      };
      
      // Track signal time
      this.lastSignalTime.set(symbol, Date.now());
      this.totalSignals++;
      logger.info(`👉 Total signals generated: ${this.totalSignals}`);
      
      return signal;
    }
    
    // Log near-crossover conditions
    const fastApproachingSlow = Math.abs(fastMA - slowMA) / slowMA < 0.01; // Within 1%
    if (fastApproachingSlow && history.length % 20 === 0) {
      logger.debug(`${symbol} - MAs converging: Fast MA ${fastMA.toFixed(2)} ~ Slow MA ${slowMA.toFixed(2)} (${((Math.abs(fastMA - slowMA) / slowMA) * 100).toFixed(2)}% diff)`);
    }
    
    return null;
  }

  private calculateSMA(prices: number[], period: number): number {
    if (prices.length < period) {
      logger.warn(`Not enough data for SMA calculation: ${prices.length} < ${period}`);
      return 0;
    }
    
    const slice = prices.slice(-period);
    const sum = slice.reduce((a, b) => a + b, 0);
    const sma = sum / period;
    
    // Sanity check
    if (isNaN(sma) || !isFinite(sma)) {
      logger.error(`Invalid SMA calculation: sum=${sum}, period=${period}, prices=${slice.length}`);
      return 0;
    }
    
    return sma;
  }
  
  private calculatePositionSize(price: number): number {
    // Get account balance from trading engine
    const tradingEngine = this.modeManager?.getTradingEngine();
    if (!tradingEngine) {
      logger.warn('No trading engine available, using default position size');
      return 100;
    }
    
    // Try to get account balance from trading engine
    let accountBalance = 100000; // Default
    try {
      if (tradingEngine.getAccountBalance) {
        accountBalance = tradingEngine.getAccountBalance();
      } else if (tradingEngine.getTotalPnl) {
        const [realized, unrealized] = tradingEngine.getTotalPnl();
        accountBalance = 100000 + realized + unrealized; // Assuming 100k initial
      }
    } catch (error) {
      logger.warn('Could not get account balance:', error);
    }
    
    const positionValue = accountBalance * this.POSITION_SIZE;
    const shares = Math.floor(positionValue / price);
    
    logger.debug(`Position sizing: Balance=$${accountBalance}, Position Size=${this.POSITION_SIZE}, Price=$${price}, Shares=${shares}`);
    
    return Math.max(1, shares); // At least 1 share
  }
  
  protected onOrderFilled(fill: any): void {
    const { symbol, side, quantity, price } = fill;
    
    const currentPosition = this.positions.get(symbol) || 0;
    
    if (side === 'buy') {
      this.positions.set(symbol, currentPosition + quantity);
      logger.info(`✅ BUY filled: ${symbol} - ${quantity} shares @ ${price}`);
    } else {
      this.positions.set(symbol, Math.max(0, currentPosition - quantity));
      logger.info(`✅ SELL filled: ${symbol} - ${quantity} shares @ ${price}`);
    }
    
    logger.info(`Position updated for ${symbol}: ${this.positions.get(symbol)} shares`);
  }
  
  // Override to provide custom order generation
  protected async signalToOrder(signal: Signal): Promise<OrderRequest | null> {
    logger.info(`🔄 Converting signal to order:`, signal);
    
    // Get position sizing from metadata or calculate
    const quantity = signal.metadata?.quantity || 100;
    
    if (signal.type === 'buy') {
      const order: OrderRequest = {
        symbol: signal.symbol,
        side: 'buy',
        quantity,
        orderType: 'market',
        timeInForce: 'DAY'
      };
      logger.info(`📈 Generated BUY order:`, order);
      return order;
    } else if (signal.type === 'sell') {
      const order: OrderRequest = {
        symbol: signal.symbol,
        side: 'sell',
        quantity,
        orderType: 'market',
        timeInForce: 'DAY'
      };
      logger.info(`📉 Generated SELL order:`, order);
      return order;
    }
    
    return null;
  }
}