import { HttpException, HttpStatus } from '@nestjs/common';

/**
 * Custom HTTP exception class that standardizes error responses across the application.
 * Extends NestJS's HttpException to provide consistent error structure.
 *
 * This class formats all error responses with a standardized structure containing:
 * - success: Always false for error responses
 * - errors: The error details/messages
 * - data: Always null for error responses
 *
 * @example
 * // Throwing with a simple string error
 * throw new CustomException('User not found', HttpStatus.NOT_FOUND);
 *
 * @example
 * // Throwing with detailed error object
 * throw new CustomException({
 *   email: 'Email is required',
 *   password: 'Password must be at least 8 characters'
 * }, HttpStatus.BAD_REQUEST);
 *
 * @example
 * // Throwing with single field error
 * throw new CustomException({ field: 'Invalid input value' }, HttpStatus.UNPROCESSABLE_ENTITY);
 */
export class CustomException extends HttpException {
  /**
   * Creates a new CustomException instance
   * @param errors - Error information. Can be either:
   *                 - A string: Converted to { message: string }
   *                 - An object: Can contain multiple error fields with descriptions
   * @param status - HTTP status code (defaults to HttpStatus.BAD_REQUEST - 400)
   */
  constructor(
    errors: Record<string, any> | string,
    status: HttpStatus = HttpStatus.BAD_REQUEST,
  ) {
    let errorObject: any = {};

    // Convert string errors to object format for consistency
    if (typeof errors === 'string') {
      // Simple error message format
      errorObject = { message: errors };
    } else {
      // Copy the error object to avoid mutation of the original
      errorObject = { ...errors };
    }

    // Call parent HttpException constructor with standardized response structure
    super(
      {
        // Always false for error responses
        success: false,

        // Contains the error details (single message or multiple field errors)
        errors: errorObject,

        // Always null for error responses (data only present in successful responses)
        data: null,
      },
      status,
    );
  }
}

/**
 * Example error response format:
 *
 * String error:
 * {
 *   "success": false,
 *   "errors": { "message": "User not found" },
 *   "data": null
 * }
 *
 * Object error:
 * {
 *   "success": false,
 *   "errors": {
 *     "email": "Email is required",
 *     "password": "Password must be at least 8 characters"
 *   },
 *   "data": null
 * }
 */
