import { v4 as uuidv4 } from 'uuid';
import { getLogger } from '@stock-bot/logger';

const logger = getLogger('backtest-service');

// Use environment variable or default
const ORCHESTRATOR_URL = process.env.ORCHESTRATOR_URL || 'http://localhost:2004';

export interface BacktestRequest {
  strategy: string;
  symbols: string[];
  startDate: string;
  endDate: string;
  initialCapital: number;
  config?: Record<string, any>;
}

export interface BacktestJob {
  id: string;
  status: 'pending' | 'running' | 'completed' | 'failed' | 'cancelled';
  strategy: string;
  symbols: string[];
  startDate: Date;
  endDate: Date;
  initialCapital: number;
  config: Record<string, any>;
  createdAt: Date;
  updatedAt: Date;
  error?: string;
}

// In-memory storage for demo (replace with database)
const backtestStore = new Map<string, BacktestJob>();
const backtestResults = new Map<string, any>();

export class BacktestService {
  async createBacktest(request: BacktestRequest): Promise<BacktestJob> {
    const backtestId = uuidv4();
    
    // Store in memory (replace with database)
    const backtest: BacktestJob = {
      id: backtestId,
      status: 'pending',
      strategy: request.strategy,
      symbols: request.symbols,
      startDate: new Date(request.startDate),
      endDate: new Date(request.endDate),
      initialCapital: request.initialCapital,
      config: request.config || {},
      createdAt: new Date(),
      updatedAt: new Date(),
    };

    backtestStore.set(backtestId, backtest);
    
    // Call orchestrator to run backtest
    try {
      const response = await fetch(`${ORCHESTRATOR_URL}/api/backtest/run`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          mode: 'backtest',
          startDate: new Date(request.startDate).toISOString(),
          endDate: new Date(request.endDate).toISOString(),
          symbols: request.symbols,
          strategy: request.strategy,
          initialCapital: request.initialCapital,
          dataFrequency: '1d', // Default to daily
          commission: request.config?.commission,
          slippage: request.config?.slippage,
          speed: 'max', // Default speed
          fillModel: {
            slippage: 'realistic',
            marketImpact: true,
            partialFills: true
          }
        }),
      });

      if (!response.ok) {
        throw new Error(`Orchestrator returned ${response.status}`);
      }

      const result = await response.json();
      
      // Store result directly without transformation
      if (result.status === 'completed') {
        backtest.status = 'completed';
        backtest.updatedAt = new Date();
        backtestStore.set(backtestId, backtest);
        backtestResults.set(backtestId, result);
        
        logger.info('Backtest completed', { 
          backtestId, 
          trades: result.metrics?.totalTrades,
          return: result.metrics?.totalReturn 
        });
      } else {
        // Update status to running if not completed
        backtest.status = 'running';
        backtest.updatedAt = new Date();
        backtestStore.set(backtestId, backtest);
      }
      
      logger.info('Backtest started in orchestrator', { backtestId, result });
    } catch (error) {
      logger.error('Failed to start backtest in orchestrator', { backtestId, error });
      backtest.status = 'failed';
      backtest.error = error.message;
    }
    
    return backtest;
  }

  async getBacktest(id: string): Promise<BacktestJob | null> {
    return backtestStore.get(id) || null;
  }

  async getBacktestResults(id: string): Promise<any> {
    // Return results directly without any transformation
    return backtestResults.get(id) || null;
  }

  async listBacktests(params: { limit: number; offset: number }): Promise<BacktestJob[]> {
    const all = Array.from(backtestStore.values());
    return all
      .sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime())
      .slice(params.offset, params.offset + params.limit);
  }

  async updateBacktestStatus(id: string, status: BacktestJob['status'], error?: string): Promise<void> {
    const backtest = backtestStore.get(id);
    if (backtest) {
      backtest.status = status;
      backtest.updatedAt = new Date();
      if (error) {
        backtest.error = error;
      }
      backtestStore.set(id, backtest);
    }
  }

  async cancelBacktest(id: string): Promise<void> {
    await this.updateBacktestStatus(id, 'cancelled');
    
    // Call orchestrator to stop backtest
    try {
      await fetch(`${ORCHESTRATOR_URL}/api/backtest/stop`, {
        method: 'POST',
      });
    } catch (error) {
      logger.error('Failed to stop backtest in orchestrator', { backtestId: id, error });
    }
  }
}