import { FastifyRequest, FastifyReply } from 'fastify';

/**
 * Handles errors consistently across the application.
 * Logs errors, captures them in Sentry, and returns consistent error responses.
 * 
 * @param request - The FastifyRequest object
 * @param reply - The FastifyReply object
 * @param error - The error that occurred
 * @param endpoint - The endpoint where the error occurred (for better tracing)
 * @returns A standardized error response
 */
export async function handleError(
  request: FastifyRequest,
  reply: FastifyReply,
  error: unknown,
  endpoint: string
) {
  // Ensure status code is set
  const statusCode = error instanceof SyntaxError || error instanceof TypeError || error instanceof RangeError 
    ? 400 
    : 500;
  
  reply.status(statusCode);
  
  // Log the error
  request.log.error(error);
  
  // Capture exception in Sentry with relevant context
  request.server.sentry.captureException(error, {
    extra: {
      method: request.method,
      url: request.url,
      routeParams: request.params,
      queryParams: request.query,
      bodyParams: request.body,
      ip: request.ip,
      endpoint: endpoint
    }
  });
  
  // Return a standardized error response
  return {
    success: false,
    error: error instanceof Error ? error.message : 'An unknown error occurred'
  };
}

/**
 * Custom error class for validation errors
 */
export class ValidationError extends Error {
  constructor(message: string) {
    super(message);
    this.name = 'ValidationError';
  }
}

/**
 * Custom error class for not found errors
 */
export class NotFoundError extends Error {
  constructor(message: string) {
    super(message);
    this.name = 'NotFoundError';
  }
}

/**
 * Custom error class for unauthorized errors
 */
export class UnauthorizedError extends Error {
  constructor(message: string) {
    super(message);
    this.name = 'UnauthorizedError';
  }
}

/**
 * Custom error class for forbidden errors
 */
export class ForbiddenError extends Error {
  constructor(message: string) {
    super(message);
    this.name = 'ForbiddenError';
  }
}

/**
 * Gets the appropriate status code for different error types
 * @param error The error to analyze
 * @returns The appropriate HTTP status code
 */
export function getStatusCodeForError(error: Error): number {
  if (error instanceof ValidationError) return 400;
  if (error instanceof NotFoundError) return 404;
  if (error instanceof UnauthorizedError) return 401;
  if (error instanceof ForbiddenError) return 403;
  
  // Default error types
  if (error instanceof SyntaxError) return 400;
  if (error instanceof TypeError) return 400;
  if (error instanceof RangeError) return 400;
  
  // Default to 500 for unhandled errors
  return 500;
} 