import { RustStrategy, Signal } from '../RustStrategy';
import { MarketData } from '../../types';

interface BarData {
  open: number;
  high: number;
  low: number;
  close: number;
  volume: number;
  timestamp: number;
}

export class SimpleMovingAverageCrossoverRust extends RustStrategy {
  private priceHistory: Map<string, number[]> = new Map();
  private lastCrossover: Map<string, 'golden' | 'death' | null> = new Map();
  private barsSinceSignal: Map<string, number> = new Map();
  
  private fastPeriod: number;
  private slowPeriod: number;
  private minHoldingBars: number;
  
  constructor(parameters: {
    fastPeriod?: number;
    slowPeriod?: number;
    minHoldingBars?: number;
  } = {}) {
    super('SimpleMovingAverageCrossover', `sma-crossover-${Date.now()}`, parameters);
    
    this.fastPeriod = parameters.fastPeriod || 5;
    this.slowPeriod = parameters.slowPeriod || 15;
    this.minHoldingBars = parameters.minHoldingBars || 3;
  }
  
  protected onMarketData(data: MarketData): Signal[] {
    const signals: Signal[] = [];
    
    // Only process bar data
    if (data.data.type !== 'bar') {
      return signals;
    }
    
    const bar = data.data as BarData;
    const symbol = data.symbol;
    const price = bar.close;
    
    // Update price history
    if (!this.priceHistory.has(symbol)) {
      this.priceHistory.set(symbol, []);
      this.barsSinceSignal.set(symbol, 0);
    }
    
    const history = this.priceHistory.get(symbol)!;
    history.push(price);
    
    // Keep only necessary history
    if (history.length > this.slowPeriod) {
      history.shift();
    }
    
    // Update bars since signal
    const currentBar = this.barsSinceSignal.get(symbol) || 0;
    this.barsSinceSignal.set(symbol, currentBar + 1);
    
    // Need enough data
    if (history.length < this.slowPeriod) {
      return signals;
    }
    
    // Calculate moving averages
    const fastMA = this.calculateSMA(history, this.fastPeriod);
    const slowMA = this.calculateSMA(history, this.slowPeriod);
    
    // Calculate previous MAs
    const prevHistory = history.slice(0, -1);
    const prevFastMA = this.calculateSMA(prevHistory, this.fastPeriod);
    const prevSlowMA = this.calculateSMA(prevHistory, this.slowPeriod);
    
    // Check for crossovers
    const currentPosition = this.positions.get(symbol) || 0;
    const lastCrossover = this.lastCrossover.get(symbol);
    const barsSinceSignal = this.barsSinceSignal.get(symbol) || 0;
    
    // Golden cross - bullish signal
    if (prevFastMA <= prevSlowMA && fastMA > slowMA) {
      this.lastCrossover.set(symbol, 'golden');
      
      if (currentPosition < 0) {
        // Close short position
        signals.push(this.closeSignal(symbol, 'Golden cross - Close short'));
      } else if (currentPosition === 0 && barsSinceSignal >= this.minHoldingBars) {
        // Open long position
        signals.push(this.buySignal(symbol, 0.8, 'Golden cross - Open long'));
        this.barsSinceSignal.set(symbol, 0);
      }
    }
    
    // Death cross - bearish signal
    else if (prevFastMA >= prevSlowMA && fastMA < slowMA) {
      this.lastCrossover.set(symbol, 'death');
      
      if (currentPosition > 0) {
        // Close long position
        signals.push(this.closeSignal(symbol, 'Death cross - Close long'));
      } else if (currentPosition === 0 && barsSinceSignal >= this.minHoldingBars) {
        // Open short position
        signals.push(this.sellSignal(symbol, 0.8, 'Death cross - Open short'));
        this.barsSinceSignal.set(symbol, 0);
      }
    }
    
    // Trend following - enter on pullbacks
    else if (currentPosition === 0 && barsSinceSignal >= this.minHoldingBars) {
      if (lastCrossover === 'golden' && fastMA > slowMA) {
        // Bullish trend continues
        signals.push(this.buySignal(symbol, 0.8, 'Bullish trend - Open long'));
        this.barsSinceSignal.set(symbol, 0);
      } else if (lastCrossover === 'death' && fastMA < slowMA) {
        // Bearish trend continues
        signals.push(this.sellSignal(symbol, 0.8, 'Bearish trend - Open short'));
        this.barsSinceSignal.set(symbol, 0);
      }
    }
    
    return signals;
  }
  
  private calculateSMA(prices: number[], period: number): number {
    if (prices.length < period) {
      return 0;
    }
    
    const relevantPrices = prices.slice(-period);
    const sum = relevantPrices.reduce((a, b) => a + b, 0);
    return sum / period;
  }
}