import { Hono } from 'hono';
import { z } from 'zod';
import { IServiceContainer } from '@stock-bot/di';
import { AnalyticsService } from '../../services/AnalyticsService';

const DateRangeSchema = z.object({
  startDate: z.string().datetime(),
  endDate: z.string().datetime()
});

const OptimizationRequestSchema = z.object({
  symbols: z.array(z.string()),
  returns: z.array(z.array(z.number())),
  constraints: z.object({
    minWeight: z.number().optional(),
    maxWeight: z.number().optional(),
    targetReturn: z.number().optional(),
    maxRisk: z.number().optional()
  }).optional()
});

export function createAnalyticsRoutes(container: IServiceContainer): Hono {
  const app = new Hono();
  const analyticsService = container.custom?.AnalyticsService as AnalyticsService;

  // Get performance metrics
  app.get('/performance/:portfolioId', async (c) => {
    try {
      const portfolioId = c.req.param('portfolioId');
      const query = c.req.query();
      
      const { startDate, endDate } = DateRangeSchema.parse({
        startDate: query.start_date,
        endDate: query.end_date
      });
      
      const metrics = await analyticsService.getPerformanceMetrics(
        portfolioId,
        new Date(startDate),
        new Date(endDate)
      );
      
      return c.json(metrics);
    } catch (error) {
      if (error instanceof z.ZodError) {
        return c.json({ 
          error: 'Invalid date range', 
          details: error.errors 
        }, 400);
      }
      
      container.logger.error('Error getting performance metrics:', error);
      return c.json({ 
        error: error instanceof Error ? error.message : 'Failed to get performance metrics' 
      }, 500);
    }
  });

  // Portfolio optimization
  app.post('/optimize', async (c) => {
    try {
      const body = await c.req.json();
      const request = OptimizationRequestSchema.parse(body);
      
      const result = await analyticsService.optimizePortfolio({
        returns: request.returns,
        constraints: request.constraints
      });
      
      return c.json(result);
    } catch (error) {
      if (error instanceof z.ZodError) {
        return c.json({ 
          error: 'Invalid optimization request', 
          details: error.errors 
        }, 400);
      }
      
      container.logger.error('Error optimizing portfolio:', error);
      return c.json({ 
        error: error instanceof Error ? error.message : 'Failed to optimize portfolio' 
      }, 500);
    }
  });

  // Get risk metrics
  app.get('/risk/:portfolioId', async (c) => {
    try {
      const portfolioId = c.req.param('portfolioId');
      const metrics = await analyticsService.getRiskMetrics(portfolioId);
      
      return c.json(metrics);
    } catch (error) {
      container.logger.error('Error getting risk metrics:', error);
      return c.json({ 
        error: error instanceof Error ? error.message : 'Failed to get risk metrics' 
      }, 500);
    }
  });

  // Market regime detection
  app.get('/regime', async (c) => {
    try {
      const regime = await analyticsService.detectMarketRegime();
      
      return c.json({
        regime,
        timestamp: new Date().toISOString()
      });
    } catch (error) {
      container.logger.error('Error detecting market regime:', error);
      return c.json({ 
        error: error instanceof Error ? error.message : 'Failed to detect market regime' 
      }, 500);
    }
  });

  // Calculate correlation matrix
  app.post('/correlation', async (c) => {
    try {
      const body = await c.req.json();
      const { symbols } = z.object({
        symbols: z.array(z.string()).min(2)
      }).parse(body);
      
      const matrix = await analyticsService.calculateCorrelationMatrix(symbols);
      
      return c.json({
        symbols,
        matrix
      });
    } catch (error) {
      if (error instanceof z.ZodError) {
        return c.json({ 
          error: 'Invalid correlation request', 
          details: error.errors 
        }, 400);
      }
      
      container.logger.error('Error calculating correlation:', error);
      return c.json({ 
        error: error instanceof Error ? error.message : 'Failed to calculate correlation' 
      }, 500);
    }
  });

  // ML model prediction
  app.post('/predict', async (c) => {
    try {
      const body = await c.req.json();
      const { modelId, features } = z.object({
        modelId: z.string(),
        features: z.record(z.number())
      }).parse(body);
      
      const prediction = await analyticsService.predictWithModel(modelId, features);
      
      if (prediction) {
        return c.json(prediction);
      } else {
        return c.json({ error: 'Model not found or prediction failed' }, 404);
      }
    } catch (error) {
      if (error instanceof z.ZodError) {
        return c.json({ 
          error: 'Invalid prediction request', 
          details: error.errors 
        }, 400);
      }
      
      container.logger.error('Error making prediction:', error);
      return c.json({ 
        error: error instanceof Error ? error.message : 'Failed to make prediction' 
      }, 500);
    }
  });

  return app;
}