import { Router } from 'express';
import { BacktestServiceV2 } from '../services/backtest-v2.service';
import type { IServiceContainer } from '@stock-bot/handlers';
import { getLogger } from '@stock-bot/logger';

const logger = getLogger('backtests-v2-router');

export function createBacktestsV2Router(container: IServiceContainer): Router {
  const router = Router();
  const backtestService = new BacktestServiceV2(container);

  // Backtest endpoints
  router.get('/backtests', async (req, res) => {
    try {
      const limit = parseInt(req.query.limit as string) || 50;
      const offset = parseInt(req.query.offset as string) || 0;
      
      const backtests = await backtestService.listBacktests({ limit, offset });
      res.json(backtests);
    } catch (error) {
      logger.error('Failed to list backtests', error);
      res.status(500).json({ error: 'Failed to list backtests' });
    }
  });

  router.get('/backtests/:id', async (req, res) => {
    try {
      const backtest = await backtestService.getBacktest(req.params.id);
      if (!backtest) {
        return res.status(404).json({ error: 'Backtest not found' });
      }
      res.json(backtest);
    } catch (error) {
      logger.error('Failed to get backtest', error);
      res.status(500).json({ error: 'Failed to get backtest' });
    }
  });

  router.post('/backtests', async (req, res) => {
    try {
      const backtest = await backtestService.createBacktest(req.body);
      res.status(201).json(backtest);
    } catch (error) {
      logger.error('Failed to create backtest', error);
      res.status(500).json({ error: 'Failed to create backtest' });
    }
  });

  router.put('/backtests/:id', async (req, res) => {
    try {
      const backtest = await backtestService.updateBacktest(req.params.id, req.body);
      if (!backtest) {
        return res.status(404).json({ error: 'Backtest not found' });
      }
      res.json(backtest);
    } catch (error) {
      logger.error('Failed to update backtest', error);
      res.status(500).json({ error: 'Failed to update backtest' });
    }
  });

  router.delete('/backtests/:id', async (req, res) => {
    try {
      await backtestService.deleteBacktest(req.params.id);
      res.status(204).send();
    } catch (error) {
      logger.error('Failed to delete backtest', error);
      res.status(500).json({ error: 'Failed to delete backtest' });
    }
  });

  // Run endpoints
  router.get('/backtests/:backtestId/runs', async (req, res) => {
    try {
      const runs = await backtestService.listRuns(req.params.backtestId);
      res.json(runs);
    } catch (error) {
      logger.error('Failed to list runs', error);
      res.status(500).json({ error: 'Failed to list runs' });
    }
  });

  router.post('/backtests/:backtestId/runs', async (req, res) => {
    try {
      const run = await backtestService.createRun({
        backtestId: req.params.backtestId,
        speedMultiplier: req.body.speedMultiplier
      });
      res.status(201).json(run);
    } catch (error) {
      logger.error('Failed to create run', error);
      res.status(500).json({ error: 'Failed to create run' });
    }
  });

  router.get('/runs/:id', async (req, res) => {
    try {
      const run = await backtestService.getRun(req.params.id);
      if (!run) {
        return res.status(404).json({ error: 'Run not found' });
      }
      res.json(run);
    } catch (error) {
      logger.error('Failed to get run', error);
      res.status(500).json({ error: 'Failed to get run' });
    }
  });

  router.get('/runs/:id/results', async (req, res) => {
    try {
      const results = await backtestService.getRunResults(req.params.id);
      if (!results) {
        return res.status(404).json({ error: 'Results not found' });
      }
      res.json(results);
    } catch (error) {
      logger.error('Failed to get run results', error);
      res.status(500).json({ error: 'Failed to get run results' });
    }
  });

  router.post('/runs/:id/pause', async (req, res) => {
    try {
      await backtestService.pauseRun(req.params.id);
      res.json({ message: 'Run paused' });
    } catch (error) {
      logger.error('Failed to pause run', error);
      res.status(500).json({ error: 'Failed to pause run' });
    }
  });

  router.post('/runs/:id/resume', async (req, res) => {
    try {
      await backtestService.resumeRun(req.params.id);
      res.json({ message: 'Run resumed' });
    } catch (error) {
      logger.error('Failed to resume run', error);
      res.status(500).json({ error: 'Failed to resume run' });
    }
  });

  router.post('/runs/:id/cancel', async (req, res) => {
    try {
      await backtestService.cancelRun(req.params.id);
      res.json({ message: 'Run cancelled' });
    } catch (error) {
      logger.error('Failed to cancel run', error);
      res.status(500).json({ error: 'Failed to cancel run' });
    }
  });

  router.put('/runs/:id/speed', async (req, res) => {
    try {
      await backtestService.updateRunSpeed(req.params.id, req.body.speedMultiplier);
      res.json({ message: 'Speed updated' });
    } catch (error) {
      logger.error('Failed to update run speed', error);
      res.status(500).json({ error: 'Failed to update run speed' });
    }
  });

  // WebSocket endpoint for real-time run updates
  router.ws('/runs/:id/stream', (ws, req) => {
    const runId = req.params.id;
    logger.info('WebSocket connection established for run', { runId });

    // TODO: Implement real-time updates
    ws.on('message', (msg) => {
      logger.debug('Received WebSocket message', { runId, msg });
    });

    ws.on('close', () => {
      logger.info('WebSocket connection closed', { runId });
    });
  });

  return router;
}