import { Application, Request, Response } from 'express';
import { ErrorHandler } from '../../utils/error-handler.js';

export function setupErrorsAPI(app: Application, errorHandler: ErrorHandler): void {
  // Error analysis API endpoints setup

  // Get error timeline
  app.get('/api/errors/timeline', async (req: Request, res: Response) => {
    try {
      const { 
        timeRange = '24h', 
        toolName, 
        severity,
        includeContext = 'true',
        limit = 100,
        offset = 0
      } = req.query;
      
      const options = {
        timeRange: timeRange as string,
        toolName: toolName as string,
        severity: severity as string,
        includeContext: includeContext === 'true',
        limit: Number(limit),
        offset: Number(offset)
      };
      
      const timeline = await errorHandler.getErrorTimeline(options);
      
      res.json({
        success: true,
        data: {
          timeline,
          count: timeline.length,
          options
        },
        timestamp: new Date().toISOString()
      });
    } catch (error) {
      console.error('🐛 Error fetching error timeline:', error);
      res.status(500).json({
        success: false,
        error: 'Failed to fetch error timeline',
        message: (error as Error).message
      });
    }
  });

  // Get error patterns analysis
  app.get('/api/errors/patterns', async (req: Request, res: Response) => {
    try {
      const { 
        timeRange = '24h',
        errorTypes,
        minOccurrences = '2',
        groupBy = 'type'
      } = req.query;
      
      const options = {
        timeRange: timeRange as string,
        errorTypes: errorTypes ? (errorTypes as string).split(',') : undefined,
        minOccurrences: Number(minOccurrences),
        groupBy: groupBy as string
      };
      
      const patterns = await errorHandler.analyzeErrorPatterns(options);
      
      res.json({
        success: true,
        data: patterns,
        timestamp: new Date().toISOString()
      });
    } catch (error) {
      console.error('🐛 Error analyzing error patterns:', error);
      res.status(500).json({
        success: false,
        error: 'Failed to analyze error patterns',
        message: (error as Error).message
      });
    }
  });

  // Get specific error details
  app.get('/api/errors/detail/:id', async (req: Request, res: Response) => {
    try {
      const { id } = req.params;
      const { includeContext = 'true', includeSuggestions = 'true' } = req.query;
      
      const errorDetails = await errorHandler.getErrorDetails(id);
      
      if (!errorDetails) {
        return res.status(404).json({
          success: false,
          error: 'Error not found',
          errorId: id
        });
      }
      
      res.json({
        success: true,
        data: errorDetails,
        timestamp: new Date().toISOString()
      });
    } catch (error) {
      console.error(`🐛 Error fetching error details for ${req.params.id}:`, error);
      res.status(500).json({
        success: false,
        error: 'Failed to fetch error details',
        message: (error as Error).message
      });
    }
  });

  // Generate error report
  app.get('/api/errors/report', async (req: Request, res: Response) => {
    try {
      const { 
        reportType = 'summary',
        timeRange = '24h',
        includeRecommendations = 'true',
        outputFormat = 'json'
      } = req.query;
      
      const options = {
        reportType: reportType as string,
        timeRange: timeRange as string,
        includeRecommendations: includeRecommendations === 'true',
        outputFormat: outputFormat as string,
        saveToFile: false
      };
      
      const report = await errorHandler.generateErrorReport(options);
      
      if (outputFormat === 'json') {
        res.json({
          success: true,
          data: report,
          timestamp: new Date().toISOString()
        });
      } else {
        // For markdown or other formats, return as text
        res.setHeader('Content-Type', 'text/plain');
        res.send(report.content || report);
      }
    } catch (error) {
      console.error('🐛 Error generating error report:', error);
      res.status(500).json({
        success: false,
        error: 'Failed to generate error report',
        message: (error as Error).message
      });
    }
  });

  // Get error statistics and metrics
  app.get('/api/errors/stats', async (req: Request, res: Response) => {
    try {
      const { timeRange = '24h' } = req.query;
      
      // Get patterns to calculate statistics
      const patterns = await errorHandler.analyzeErrorPatterns({
        timeRange: timeRange as string,
        minOccurrences: 1,
        groupBy: 'type'
      });
      
      const timeline = await errorHandler.getErrorTimeline({
        timeRange: timeRange as string
      });
      
      // Calculate statistics
      const errorsByType = timeline.reduce((acc: any, error: any) => {
        acc[error.type] = (acc[error.type] || 0) + 1;
        return acc;
      }, {});
      
      const errorsBySeverity = timeline.reduce((acc: any, error: any) => {
        acc[error.severity] = (acc[error.severity] || 0) + 1;
        return acc;
      }, {});
      
      const errorsByTool = timeline.reduce((acc: any, error: any) => {
        const tool = error.tool || 'unknown';
        acc[tool] = (acc[tool] || 0) + 1;
        return acc;
      }, {});
      
      const stats = {
        timeRange,
        totalErrors: timeline.length,
        errorsByType,
        errorsBySeverity,
        errorsByTool,
        patternsFound: patterns.patternsFound?.length || 0,
        errorRate: calculateErrorRate(timeline, timeRange as string),
        mostCommonError: Object.keys(errorsByType).reduce((a, b) => 
          errorsByType[a] > errorsByType[b] ? a : b, 'none'
        ),
        criticalErrors: timeline.filter((e: any) => e.severity === 'critical').length,
        trends: {
          increasing: patterns.patternsFound?.filter((p: any) => p.trend === 'increasing').length || 0,
          stable: patterns.patternsFound?.filter((p: any) => p.trend === 'stable').length || 0,
          decreasing: patterns.patternsFound?.filter((p: any) => p.trend === 'decreasing').length || 0
        }
      };
      
      res.json({
        success: true,
        data: stats,
        timestamp: new Date().toISOString()
      });
    } catch (error) {
      console.error('🐛 Error fetching error statistics:', error);
      res.status(500).json({
        success: false,
        error: 'Failed to fetch error statistics',
        message: (error as Error).message
      });
    }
  });

  // Resolve error suggestion
  app.post('/api/errors/resolve', async (req: Request, res: Response) => {
    try {
      const { 
        errorId, 
        suggestionId, 
        implementation, 
        effectiveness,
        notes 
      } = req.body;
      
      if (!errorId || !suggestionId) {
        return res.status(400).json({
          success: false,
          error: 'Error ID and suggestion ID are required'
        });
      }

      const resolution = await errorHandler.resolveErrorSuggestion({
        errorId,
        suggestionId,
        implementation,
        effectiveness,
        notes
      });
      
      res.json({
        success: true,
        message: 'Error suggestion resolved successfully',
        data: resolution,
        timestamp: new Date().toISOString()
      });
    } catch (error) {
      console.error('🐛 Error resolving error suggestion:', error);
      res.status(500).json({
        success: false,
        error: 'Failed to resolve error suggestion',
        message: (error as Error).message
      });
    }
  });

  // Simulate error recovery
  app.post('/api/errors/simulate', async (req: Request, res: Response) => {
    try {
      const { 
        errorType, 
        severity = 'medium', 
        context = {},
        dryRun = true 
      } = req.body;
      
      if (!errorType) {
        return res.status(400).json({
          success: false,
          error: 'Error type is required for simulation'
        });
      }

      const simulation = await errorHandler.simulateErrorRecovery({
        errorType,
        severity,
        context,
        dryRun
      });
      
      res.json({
        success: true,
        data: simulation,
        timestamp: new Date().toISOString()
      });
    } catch (error) {
      console.error('🐛 Error simulating error recovery:', error);
      res.status(500).json({
        success: false,
        error: 'Failed to simulate error recovery',
        message: (error as Error).message
      });
    }
  });

  // Get error resolution suggestions
  app.get('/api/errors/suggestions/:id', async (req: Request, res: Response) => {
    try {
      const { id } = req.params;
      
      const errorDetails = await errorHandler.getErrorDetails(id);
      
      if (!errorDetails) {
        return res.status(404).json({
          success: false,
          error: 'Error not found',
          errorId: id
        });
      }
      
      res.json({
        success: true,
        data: {
          errorId: id,
          suggestions: errorDetails.suggestions || [],
          rootCause: errorDetails.rootCause,
          relatedErrors: errorDetails.relatedErrors || []
        },
        timestamp: new Date().toISOString()
      });
    } catch (error) {
      console.error(`🐛 Error fetching suggestions for error ${req.params.id}:`, error);
      res.status(500).json({
        success: false,
        error: 'Failed to fetch error suggestions',
        message: (error as Error).message
      });
    }
  });

  // Get error trends over time
  app.get('/api/errors/trends', async (req: Request, res: Response) => {
    try {
      const { 
        timeRange = '7d',
        granularity = 'hour',
        errorType,
        toolName 
      } = req.query;
      
      // This would be implemented with time-series data from ErrorHandler
      // For now, return mock trend data
      const trendData = generateMockTrendData(
        timeRange as string, 
        granularity as string,
        errorType as string,
        toolName as string
      );
      
      res.json({
        success: true,
        data: trendData,
        timestamp: new Date().toISOString()
      });
    } catch (error) {
      console.error('🐛 Error fetching error trends:', error);
      res.status(500).json({
        success: false,
        error: 'Failed to fetch error trends',
        message: (error as Error).message
      });
    }
  });

  // Health check for error analysis service
  app.get('/api/errors/health', async (req: Request, res: Response) => {
    try {
      // Test error handler functionality
      const testPatterns = await errorHandler.analyzeErrorPatterns({
        timeRange: '1h',
        minOccurrences: 1,
        groupBy: 'type'
      });
      
      res.json({
        success: true,
        status: 'healthy',
        data: {
          errorHandlerAvailable: true,
          patternAnalysisWorking: testPatterns ? true : false,
          features: {
            errorTimeline: true,
            patternAnalysis: true,
            errorDetails: true,
            reportGeneration: true,
            resolutionTracking: true,
            errorSimulation: true
          }
        },
        timestamp: new Date().toISOString()
      });
    } catch (error) {
      console.error('🐛 Error service health check failed:', error);
      res.status(503).json({
        success: false,
        status: 'unhealthy',
        error: 'Error analysis service is not functioning properly',
        message: (error as Error).message,
        timestamp: new Date().toISOString()
      });
    }
  });
}

function calculateErrorRate(timeline: any[], timeRange: string): number {
  if (timeline.length === 0) return 0;
  
  // Calculate errors per hour based on time range
  const hours = {
    '1h': 1,
    '6h': 6,
    '24h': 24,
    '7d': 24 * 7,
    '30d': 24 * 30
  }[timeRange] || 24;
  
  return Number((timeline.length / hours).toFixed(2));
}

function generateMockTrendData(
  timeRange: string, 
  granularity: string,
  errorType?: string,
  toolName?: string
): any {
  const now = new Date();
  const dataPoints = [];
  
  // Determine number of data points based on time range and granularity
  const intervals = {
    '1h': granularity === 'minute' ? 60 : 4, // 15-minute intervals for hour
    '24h': granularity === 'hour' ? 24 : 96, // 15-minute intervals for day
    '7d': granularity === 'day' ? 7 : 168, // hourly for week
    '30d': granularity === 'day' ? 30 : 720 // hourly for month
  }[timeRange] || 24;
  
  const intervalMs = {
    minute: 60 * 1000,
    hour: 60 * 60 * 1000,
    day: 24 * 60 * 60 * 1000
  }[granularity] || 60 * 60 * 1000;
  
  // Generate mock data with some realistic patterns
  for (let i = intervals - 1; i >= 0; i--) {
    const timestamp = new Date(now.getTime() - i * intervalMs);
    
    // Simulate error patterns (more errors during peak hours, fewer at night)
    const hour = timestamp.getHours();
    const baseRate = hour >= 9 && hour <= 17 ? 2.5 : 0.8; // Higher during work hours
    const randomVariation = Math.random() * 0.5 + 0.75; // 75-125% of base rate
    const errorCount = Math.floor(baseRate * randomVariation);
    
    dataPoints.push({
      timestamp: timestamp.toISOString(),
      errorCount,
      errorRate: Number((errorCount / (intervalMs / (60 * 60 * 1000))).toFixed(2))
    });
  }
  
  return {
    timeRange,
    granularity,
    errorType: errorType || 'all',
    toolName: toolName || 'all',
    dataPoints,
    summary: {
      totalErrors: dataPoints.reduce((sum, point) => sum + point.errorCount, 0),
      averageRate: Number((dataPoints.reduce((sum, point) => sum + point.errorRate, 0) / dataPoints.length).toFixed(2)),
      peakErrors: Math.max(...dataPoints.map(point => point.errorCount)),
      trend: dataPoints.length > 1 ? 
        (dataPoints[dataPoints.length - 1].errorCount > dataPoints[0].errorCount ? 'increasing' : 'decreasing') :
        'stable'
    }
  };
}