import { BacktestEngine } from '@stock-bot/engine';
import { MarketData } from '../types';

export interface Signal {
  symbol: string;
  signal_type: 'Buy' | 'Sell' | 'Close';
  strength: number; // -1.0 to 1.0
  quantity?: number;
  reason?: string;
  metadata?: any;
}

export interface StrategyCall {
  method: string;
  data: any;
}

export interface StrategyResponse {
  signals: Signal[];
}

/**
 * Base class for TypeScript strategies that run in the Rust backtest engine
 */
export abstract class RustStrategy {
  protected name: string;
  protected id: string;
  protected parameters: Record<string, any>;
  protected positions: Map<string, number> = new Map();
  
  constructor(name: string, id: string, parameters: Record<string, any> = {}) {
    this.name = name;
    this.id = id;
    this.parameters = parameters;
  }
  
  /**
   * Main callback that Rust will call
   */
  public handleCall(call: StrategyCall): StrategyResponse {
    switch (call.method) {
      case 'on_market_data':
        const signals = this.onMarketData(call.data);
        return { signals };
        
      case 'on_fill':
        this.onFill(
          call.data.symbol,
          call.data.quantity,
          call.data.price,
          call.data.side
        );
        return { signals: [] };
        
      default:
        return { signals: [] };
    }
  }
  
  /**
   * Called when new market data is received
   */
  protected abstract onMarketData(data: MarketData): Signal[];
  
  /**
   * Called when an order is filled
   */
  protected onFill(symbol: string, quantity: number, price: number, side: string): void {
    const currentPosition = this.positions.get(symbol) || 0;
    const newPosition = side === 'buy' ? 
      currentPosition + quantity : 
      currentPosition - quantity;
    
    if (Math.abs(newPosition) < 0.0001) {
      this.positions.delete(symbol);
    } else {
      this.positions.set(symbol, newPosition);
    }
  }
  
  /**
   * Helper to create a buy signal
   */
  protected buySignal(symbol: string, strength: number = 1.0, reason?: string): Signal {
    return {
      symbol,
      signal_type: 'Buy',
      strength,
      reason,
    };
  }
  
  /**
   * Helper to create a sell signal
   */
  protected sellSignal(symbol: string, strength: number = 1.0, reason?: string): Signal {
    return {
      symbol,
      signal_type: 'Sell',
      strength,
      reason,
    };
  }
  
  /**
   * Helper to create a close position signal
   */
  protected closeSignal(symbol: string, reason?: string): Signal {
    return {
      symbol,
      signal_type: 'Close',
      strength: 1.0,
      reason,
    };
  }
  
  /**
   * Register this strategy with a backtest engine
   */
  public register(engine: BacktestEngine): void {
    console.log(`Registering strategy ${this.name} with id ${this.id}`);
    
    // Convert the handleCall method to what Rust expects
    const callback = (callJson: string) => {
      console.log('Strategy callback called with:', callJson);
      const call: StrategyCall = JSON.parse(callJson);
      const response = this.handleCall(call);
      console.log('Strategy response:', response);
      return JSON.stringify(response);
    };
    
    engine.addTypescriptStrategy(
      this.name,
      this.id,
      this.parameters,
      callback as any
    );
  }
}