import { Hono } from 'hono';
import { z } from 'zod';
import { IServiceContainer } from '@stock-bot/di';
import { BacktestConfigSchema } from '../../types';
import { BacktestEngine } from '../../backtest/BacktestEngine';
import { ModeManager } from '../../core/ModeManager';

const BacktestIdSchema = z.object({
  backtestId: z.string()
});

export function createBacktestRoutes(container: IServiceContainer): Hono {
  const app = new Hono();
  const backtestEngine = container.custom?.BacktestEngine as BacktestEngine;
  const modeManager = container.custom?.ModeManager as ModeManager;
  
  // Default POST to / is the same as /run for backward compatibility
  app.post('/', async (c) => {
    try {
      const body = await c.req.json();
      const config = BacktestConfigSchema.parse(body);
      
      // Initialize backtest mode
      await modeManager.initializeMode(config);
      
      // Run backtest
      const result = await backtestEngine.runBacktest(config);
      
      return c.json(result, 201);
    } catch (error) {
      if (error instanceof z.ZodError) {
        return c.json({ 
          error: 'Invalid backtest configuration', 
          details: error.errors 
        }, 400);
      }
      
      container.logger.error('Error running backtest:', error);
      return c.json({ 
        error: error instanceof Error ? error.message : 'Failed to run backtest' 
      }, 500);
    }
  });
  
  // Run new backtest (same as above but at /run)
  app.post('/run', async (c) => {
    try {
      const body = await c.req.json();
      const config = BacktestConfigSchema.parse(body);
      
      // Initialize backtest mode
      await modeManager.initializeMode(config);
      
      // Run backtest
      const result = await backtestEngine.runBacktest(config);
      
      return c.json(result, 201);
    } catch (error) {
      if (error instanceof z.ZodError) {
        return c.json({ 
          error: 'Invalid backtest configuration', 
          details: error.errors 
        }, 400);
      }
      
      container.logger.error('Error running backtest:', error);
      return c.json({ 
        error: error instanceof Error ? error.message : 'Failed to run backtest' 
      }, 500);
    }
  });

  // Stop running backtest
  app.post('/stop', async (c) => {
    try {
      await backtestEngine.stopBacktest();
      
      return c.json({ 
        message: 'Backtest stop requested',
        timestamp: new Date().toISOString()
      });
    } catch (error) {
      container.logger.error('Error stopping backtest:', error);
      return c.json({ 
        error: error instanceof Error ? error.message : 'Failed to stop backtest' 
      }, 500);
    }
  });
  
  // Pause running backtest
  app.post('/pause', async (c) => {
    try {
      await backtestEngine.pauseBacktest();
      
      return c.json({ 
        message: 'Backtest paused',
        timestamp: new Date().toISOString()
      });
    } catch (error) {
      container.logger.error('Error pausing backtest:', error);
      return c.json({ 
        error: error instanceof Error ? error.message : 'Failed to pause backtest' 
      }, 500);
    }
  });
  
  // Resume paused backtest
  app.post('/resume', async (c) => {
    try {
      await backtestEngine.resumeBacktest();
      
      return c.json({ 
        message: 'Backtest resumed',
        timestamp: new Date().toISOString()
      });
    } catch (error) {
      container.logger.error('Error resuming backtest:', error);
      return c.json({ 
        error: error instanceof Error ? error.message : 'Failed to resume backtest' 
      }, 500);
    }
  });
  
  // Set backtest speed
  app.post('/speed', async (c) => {
    try {
      const body = await c.req.json();
      const speed = body.speed ?? 1;
      
      backtestEngine.setSpeedMultiplier(speed);
      
      return c.json({ 
        message: 'Backtest speed updated',
        speed: speed === null ? 'unlimited' : speed,
        timestamp: new Date().toISOString()
      });
    } catch (error) {
      container.logger.error('Error setting backtest speed:', error);
      return c.json({ 
        error: error instanceof Error ? error.message : 'Failed to set speed' 
      }, 500);
    }
  });

  // Get backtest progress
  app.get('/progress', async (c) => {
    try {
      const status = backtestEngine.getStatus();
      
      return c.json({
        status: status.isPaused ? 'paused' : (status.isRunning ? 'running' : 'idle'),
        progress: status.progress,
        currentTime: new Date(status.currentTime).toISOString(),
        isRunning: status.isRunning,
        isPaused: status.isPaused
      });
    } catch (error) {
      container.logger.error('Error getting backtest progress:', error);
      return c.json({ 
        error: error instanceof Error ? error.message : 'Failed to get progress' 
      }, 500);
    }
  });

  // Stream backtest events (Server-Sent Events)
  app.get('/stream', async (c) => {
    c.header('Content-Type', 'text/event-stream');
    c.header('Cache-Control', 'no-cache');
    c.header('Connection', 'keep-alive');
    
    const stream = new ReadableStream({
      start(controller) {
        // Listen for backtest events
        const onProgress = (data: any) => {
          controller.enqueue(`data: ${JSON.stringify(data)}\n\n`);
        };
        
        const onComplete = (data: any) => {
          controller.enqueue(`data: ${JSON.stringify({ event: 'complete', data })}\n\n`);
          controller.close();
        };
        
        backtestEngine.on('progress', onProgress);
        backtestEngine.on('complete', onComplete);
        
        // Cleanup on close
        c.req.raw.signal.addEventListener('abort', () => {
          backtestEngine.off('progress', onProgress);
          backtestEngine.off('complete', onComplete);
          controller.close();
        });
      }
    });
    
    return new Response(stream);
  });

  // Validate backtest configuration
  app.post('/validate', async (c) => {
    try {
      const body = await c.req.json();
      const config = BacktestConfigSchema.parse(body);
      
      // Additional validation logic
      const validation = {
        valid: true,
        warnings: [] as string[],
        estimatedDuration: 0
      };
      
      // Check data availability
      const startDate = new Date(config.startDate);
      const endDate = new Date(config.endDate);
      const days = (endDate.getTime() - startDate.getTime()) / (1000 * 60 * 60 * 24);
      
      if (days > 365) {
        validation.warnings.push('Large date range may take significant time to process');
      }
      
      if (config.symbols.length > 100) {
        validation.warnings.push('Large number of symbols may impact performance');
      }
      
      // Estimate duration (simplified)
      validation.estimatedDuration = days * config.symbols.length * 0.1; // seconds
      
      return c.json(validation);
    } catch (error) {
      if (error instanceof z.ZodError) {
        return c.json({ 
          valid: false,
          error: 'Invalid configuration', 
          details: error.errors 
        }, 400);
      }
      
      return c.json({ 
        valid: false,
        error: error instanceof Error ? error.message : 'Validation failed' 
      }, 500);
    }
  });

  return app;
}