/**
 * Custom Error Classes
 * Application-specific error classes for better error handling
 */

/**
 * Base application error class
 * Extends native Error class
 */
class AppError extends Error {
  constructor(message, statusCode = 500) {
    super(message); // Call parent Error constructor
    this.statusCode = statusCode; // HTTP status code
    this.isOperational = true; // Mark as operational error (expected)
    Error.captureStackTrace(this, this.constructor); // Capture stack trace
  }
}

/**
 * Validation error class
 * Used for input validation failures
 */
class ValidationError extends AppError {
  constructor(message = 'Validation Error', errors = null) {
    super(message, 400); // Set status code to 400 (Bad Request)
    this.errors = errors; // Store validation error details
    this.name = 'ValidationError'; // Error name
  }
}

/**
 * Not found error class
 * Used when a requested resource is not found
 */
class NotFoundError extends AppError {
  constructor(message = 'Resource not found') {
    super(message, 404); // Set status code to 404 (Not Found)
    this.name = 'NotFoundError'; // Error name
  }
}

/**
 * Unauthorized error class
 * Used for authentication failures
 */
class UnauthorizedError extends AppError {
  constructor(message = 'Unauthorized') {
    super(message, 401); // Set status code to 401 (Unauthorized)
    this.name = 'UnauthorizedError'; // Error name
  }
}

/**
 * Conflict error class
 * Used for resource conflicts (e.g., duplicate username, email)
 */
class ConflictError extends AppError {
  constructor(message = 'Conflict') {
    super(message, 409); // Set status code to 409 (Conflict)
    this.name = 'ConflictError'; // Error name
  }
}

/**
 * Forbidden error class
 * Used for authorization failures (user lacks permission)
 */
class ForbiddenError extends AppError {
  constructor(message = 'Forbidden') {
    super(message, 403); // Set status code to 403 (Forbidden)
    this.name = 'ForbiddenError'; // Error name
  }
}

/**
 * Bad request error class
 * Used for malformed requests
 */
class BadRequestError extends AppError {
  constructor(message = 'Bad Request') {
    super(message, 400); // Set status code to 400 (Bad Request)
    this.name = 'BadRequestError'; // Error name
  }
}

/**
 * Inventory error class
 * Used for inventory-related errors (e.g., insufficient stock)
 */
class InventoryError extends AppError {
  constructor(message = 'Inventory error', statusCode = 400) {
    super(message, statusCode); // Allow custom status code
    this.name = 'InventoryError'; // Error name
  }
}

/**
 * KRA eTIMS error class
 * Used for KRA eTIMS integration errors
 */
class KRAError extends AppError {
  constructor(message = 'KRA eTIMS error', statusCode = 502) {
    super(message, statusCode); // Default to 502 (Bad Gateway)
    this.name = 'KRAError'; // Error name
  }
}

// Export all error classes
module.exports = {
  AppError, // Base application error
  ValidationError, // Validation error
  NotFoundError, // Not found error
  UnauthorizedError, // Unauthorized error
  ForbiddenError, // Forbidden error
  ConflictError, // Conflict error
  BadRequestError, // Bad request error
  InventoryError, // Inventory error
  KRAError, // KRA eTIMS error
};

