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

export interface IStrategyExecutor {
  onMarketData(data: MarketData): Signal[];
  onFill(symbol: string, quantity: number, price: number, side: string): void;
  getState(): any;
  setState(state: any): void;
}

/**
 * Executes strategies in-process for backtesting
 * This avoids the complexity of async callbacks between Rust and TypeScript
 */
export class StrategyExecutor implements IStrategyExecutor {
  private strategies: Map<string, any> = new Map();
  private strategyStates: Map<string, any> = new Map();
  
  registerStrategy(id: string, strategy: any) {
    this.strategies.set(id, strategy);
    this.strategyStates.set(id, {
      priceHistory: new Map<string, number[]>(),
      positions: new Map<string, number>(),
    });
  }
  
  onMarketData(data: MarketData): Signal[] {
    const allSignals: Signal[] = [];
    
    for (const [id, strategy] of this.strategies) {
      const state = this.strategyStates.get(id)!;
      const signals = strategy.onMarketData(data, state);
      
      if (signals && signals.length > 0) {
        allSignals.push(...signals);
      }
    }
    
    return allSignals;
  }
  
  onFill(symbol: string, quantity: number, price: number, side: string): void {
    for (const [id, strategy] of this.strategies) {
      const state = this.strategyStates.get(id)!;
      
      if (strategy.onFill) {
        strategy.onFill({ symbol, quantity, price, side }, state);
      }
      
      // Update position tracking
      const currentPos = state.positions.get(symbol) || 0;
      const newPos = side === 'buy' ? currentPos + quantity : currentPos - quantity;
      
      if (Math.abs(newPos) < 0.0001) {
        state.positions.delete(symbol);
      } else {
        state.positions.set(symbol, newPos);
      }
    }
  }
  
  getState(): any {
    return Object.fromEntries(this.strategyStates);
  }
  
  setState(state: any): void {
    this.strategyStates = new Map(Object.entries(state));
  }
}

// Example SMA Crossover Strategy
export const SMACrossoverStrategy = {
  onMarketData(data: MarketData, state: any): Signal[] {
    const signals: Signal[] = [];
    
    // Check if it's bar data
    if (data.type !== 'bar') return signals;
    
    const { symbol, close } = data.data;
    const fastPeriod = 5;
    const slowPeriod = 15;
    
    // Update price history
    if (!state.priceHistory.has(symbol)) {
      state.priceHistory.set(symbol, []);
    }
    
    const history = state.priceHistory.get(symbol)!;
    history.push(close);
    
    // Keep only necessary history
    if (history.length > slowPeriod + 1) {
      history.shift();
    }
    
    // Need enough data
    if (history.length >= slowPeriod) {
      // Calculate SMAs
      const fastSMA = history.slice(-fastPeriod).reduce((a, b) => a + b, 0) / fastPeriod;
      const slowSMA = history.reduce((a, b) => a + b, 0) / history.length;
      
      // Previous SMAs (if we have enough history)
      if (history.length > slowPeriod) {
        const prevHistory = history.slice(0, -1);
        const prevFastSMA = prevHistory.slice(-fastPeriod).reduce((a, b) => a + b, 0) / fastPeriod;
        const prevSlowSMA = prevHistory.reduce((a, b) => a + b, 0) / prevHistory.length;
        
        const currentPosition = state.positions.get(symbol) || 0;
        
        // Golden cross - buy signal
        if (prevFastSMA <= prevSlowSMA && fastSMA > slowSMA && currentPosition <= 0) {
          signals.push({
            symbol,
            signal_type: 'Buy',
            strength: 1.0,
            quantity: 100,
            reason: 'Golden cross',
          });
        }
        
        // Death cross - sell signal
        else if (prevFastSMA >= prevSlowSMA && fastSMA < slowSMA && currentPosition >= 0) {
          signals.push({
            symbol,
            signal_type: 'Sell',
            strength: 1.0,
            quantity: 100,
            reason: 'Death cross',
          });
        }
      }
    }
    
    return signals;
  },
};