import { Request, Response, NextFunction } from 'express';
import { ApiError } from '../../utils/errors/api.error';
import { DatabaseError } from '../../utils/errors/database.error';
import { AuthError } from '../../utils/errors/auth.error';
import logger from '../../config/logger';

/**
 * Global error handling middleware
 * Catches all errors thrown in the application and formats the response
 */
export const errorMiddleware = (
  err: Error,
  req: Request,
  res: Response,
  next: NextFunction
): void => {
  // Log the error
  logger.error(`Error occurred: ${err.message}`, {
    method: req.method,
    url: req.url,
    error: err.stack
  });

  // Handle specific error types
  if (err instanceof ApiError) {
    res.status(err.statusCode).json({
      status: 'error',
      message: err.message,
      code: err.code
    });
    return;
  }

  if (err instanceof DatabaseError) {
    res.status(500).json({
      status: 'error',
      message: 'Database error occurred',
      code: 'DATABASE_ERROR'
    });
    return;
  }

  if (err instanceof AuthError) {
    res.status(401).json({
      status: 'error',
      message: 'Authentication error',
      code: 'AUTH_ERROR'
    });
    return;
  }

  // Handle validation errors from express-validator
  if (err instanceof Error && 'errors' in (err as any)) {
    res.status(400).json({
      status: 'error',
      message: 'Validation failed',
      code: 'VALIDATION_ERROR',
      errors: (err as any).errors
    });
    return;
  }

  // Default error handler
  // Don't expose error details in production for security reasons
  const isDevelopment = process.env.NODE_ENV === 'development';

  res.status(500).json({
    status: 'error',
    message: 'Internal server error',
    code: 'INTERNAL_SERVER_ERROR',
    ...(isDevelopment && { stack: err.stack })
  });
};

/**
 * Not found middleware
 * Handles 404 errors for routes that don't exist
 */
export const notFoundMiddleware = (
  req: Request,
  res: Response,
  next: NextFunction
): void => {
  res.status(404).json({
    status: 'error',
    message: 'Resource not found',
    code: 'NOT_FOUND'
  });
};
