/**
 * @desc Custom API error class that extends the built-in Error class
 * @param {string} message - Error message
 * @param {number} statusCode - HTTP status code
 * @param {string} [stack=''] - Error stack trace
 * @param {boolean} [isOperational=true] - Indicates if the error is operational
 * @param {Array} [errors=[]] - Array of validation errors or additional error details
 */
class ApiError extends Error {
  constructor(
    message,
    statusCode,
    stack = '',
    isOperational = true,
    errors = []
  ) {
    super(message);
    this.statusCode = statusCode;
    this.status = `${statusCode}`.startsWith('4') ? 'fail' : 'error';
    this.isOperational = isOperational;
    this.errors = errors;

    if (stack) {
      this.stack = stack;
    } else {
      Error.captureStackTrace(this, this.constructor);
    }
  }

  /**
   * Create a bad request error (400)
   * @param {string} [message='Bad Request'] - Error message
   * @param {Array} [errors=[]] - Array of validation errors
   * @returns {ApiError}
   */
  static badRequest(message = 'Bad Request', errors = []) {
    return new ApiError(message, 400, '', true, errors);
  }

  /**
   * Create an unauthorized error (401)
   * @param {string} [message='Unauthorized'] - Error message
   * @returns {ApiError}
   */
  static unauthorized(message = 'Unauthorized') {
    return new ApiError(message, 401);
  }

  /**
   * Create a forbidden error (403)
   * @param {string} [message='Forbidden'] - Error message
   * @returns {ApiError}
   */
  static forbidden(message = 'Forbidden') {
    return new ApiError(message, 403);
  }

  /**
   * Create a not found error (404)
   * @param {string} [message='Resource not found'] - Error message
   * @returns {ApiError}
   */
  static notFound(message = 'Resource not found') {
    return new ApiError(message, 404);
  }

  /**
   * Create a validation error (422)
   * @param {string} [message='Validation Error'] - Error message
   * @param {Array} [errors=[]] - Array of validation errors
   * @returns {ApiError}
   */
  static validationError(message = 'Validation Error', errors = []) {
    return new ApiError(message, 422, '', true, errors);
  }

  /**
   * Create an internal server error (500)
   * @param {string} [message='Internal Server Error'] - Error message
   * @param {Error} [error] - Original error object
   * @returns {ApiError}
   */
  static internal(message = 'Internal Server Error', error = null) {
    const stack = error ? error.stack : '';
    return new ApiError(message, 500, stack, false);
  }
}

module.exports = ApiError;
