import { Request, Response, NextFunction } from 'express';
import { GenerateImageResponse } from '../types/api';

/**
 * Global error handler for the Express application
 */
export const errorHandler = (error: Error, req: Request, res: Response, next: NextFunction) => {
  const timestamp = new Date().toISOString();
  const requestId = req.requestId || 'unknown';

  // Log the error
  console.error(`[${timestamp}] [${requestId}] ERROR:`, {
    message: error.message,
    stack: error.stack,
    path: req.path,
    method: req.method,
    body: req.body,
    query: req.query,
  });

  // Don't send error response if headers already sent
  if (res.headersSent) {
    return next(error);
  }

  // Determine error type and status code
  let statusCode = 500;
  let errorMessage = 'Internal server error';
  let errorType = 'INTERNAL_ERROR';

  if (error.name === 'ValidationError') {
    statusCode = 400;
    errorMessage = error.message;
    errorType = 'VALIDATION_ERROR';
  } else if (error.message.includes('API key') || error.message.includes('authentication')) {
    statusCode = 401;
    errorMessage = 'Authentication failed';
    errorType = 'AUTH_ERROR';
  } else if (error.message.includes('not found') || error.message.includes('404')) {
    statusCode = 404;
    errorMessage = 'Resource not found';
    errorType = 'NOT_FOUND';
  } else if (error.message.includes('timeout') || error.message.includes('503')) {
    statusCode = 503;
    errorMessage = 'Service temporarily unavailable';
    errorType = 'SERVICE_UNAVAILABLE';
  } else if (error.message.includes('overloaded') || error.message.includes('rate limit')) {
    statusCode = 429;
    errorMessage = 'Service overloaded, please try again later';
    errorType = 'RATE_LIMITED';
  }

  // Create error response
  const errorResponse: GenerateImageResponse = {
    success: false,
    message: 'Request failed',
    error: errorMessage,
  };

  // Add additional debug info in development
  if (process.env['NODE_ENV'] === 'development') {
    (errorResponse as any).debug = {
      originalError: error.message,
      errorType,
      requestId,
      timestamp,
    };
  }

  console.log(
    `[${timestamp}] [${requestId}] Sending error response: ${statusCode} - ${errorMessage}`,
  );

  res.status(statusCode).json(errorResponse);
};

/**
 * 404 handler for unmatched routes
 */
export const notFoundHandler = (req: Request, res: Response) => {
  const timestamp = new Date().toISOString();
  const requestId = req.requestId || 'unknown';

  console.log(`[${timestamp}] [${requestId}] 404 - Route not found: ${req.method} ${req.path}`);

  const notFoundResponse: GenerateImageResponse = {
    success: false,
    message: 'Route not found',
    error: `The requested endpoint ${req.method} ${req.path} does not exist`,
  };

  res.status(404).json(notFoundResponse);
};

/**
 * Async error wrapper to catch errors in async route handlers
 */
export const asyncHandler = (fn: Function) => (req: Request, res: Response, next: NextFunction) => {
  Promise.resolve(fn(req, res, next)).catch(next);
};
