/**
 * @module ErrorClasses
 * @description Error classes for the A2A protocol client
 * 
 * This module provides a set of standardized error classes for the A2A SDK.
 * These classes help with consistent error handling and provide detailed
 * information about what went wrong during operations.
 */

/**
 * Base error class for all A2A protocol errors
 * 
 * This is the parent class for all errors in the A2A SDK. It extends the standard
 * JavaScript Error class and adds properties for error code and details.
 * 
 * @example
 * ```typescript
 * try {
 *   // SDK operation that might fail
 * } catch (error) {
 *   if (error instanceof A2AError) {
 *     console.error(`A2A Error (${error.code}): ${error.message}`);
 *     console.error('Details:', error.details);
 *   }
 * }
 * ```
 */
export class A2AError extends Error {
  /**
   * Creates a new A2A error
   * 
   * @param code - Error code identifying the error type
   * @param message - Human-readable error message
   * @param details - Optional additional error details
   */
  constructor(
    public readonly code: string,
    message: string,
    public readonly details?: Record<string, unknown>
  ) {
    super(message);
    this.name = 'A2AError';
  }
}

/**
 * Error class for client-side errors in the A2A SDK
 * 
 * This class represents errors that occur on the client side, such as validation
 * errors, network issues, or timeouts. The error code is automatically prefixed
 * with "CLIENT_".
 * 
 * @example
 * ```typescript
 * throw new A2AClientError(
 *   'INVALID_PARAMETER',
 *   'The parameter "agentId" is required',
 *   { parameter: 'agentId' }
 * );
 * ```
 */
export class A2AClientError extends A2AError {
  /**
   * Creates a new client-side error
   * 
   * @param code - Error code without the "CLIENT_" prefix
   * @param message - Human-readable error message
   * @param details - Optional additional error details
   */
  constructor(
    code: string,
    message: string,
    details?: Record<string, unknown>
  ) {
    super(`CLIENT_${code}`, message, details);
    this.name = 'A2AClientError';
  }
}

/**
 * Error class for server-side errors in the A2A protocol
 * 
 * This class represents errors that occur on the server side, such as
 * authentication failures, resource not found, or internal server errors.
 * The error code is automatically prefixed with "SERVER_".
 * 
 * @example
 * ```typescript
 * throw new A2AServerError(
 *   404,
 *   'NOT_FOUND',
 *   'The requested agent was not found',
 *   { agentId: 'missing-agent' }
 * );
 * ```
 */
export class A2AServerError extends A2AError {
  /**
   * Creates a new server-side error
   * 
   * @param status - HTTP status code associated with the error
   * @param code - Error code without the "SERVER_" prefix
   * @param message - Human-readable error message
   * @param details - Optional additional error details
   */
  constructor(
    public readonly status: number,
    code: string,
    message: string,
    details?: Record<string, unknown>
  ) {
    super(`SERVER_${code}`, message, details);
    this.name = 'A2AServerError';
  }
}

/**
 * Error class for network-related errors
 * 
 * This class represents errors that occur during network operations, such as
 * connection failures, DNS resolution issues, or timeouts.
 * 
 * @example
 * ```typescript
 * try {
 *   await fetch('https://a2a-server.example.com');
 * } catch (error) {
 *   throw new A2ANetworkError('Failed to connect to server', { originalError: error });
 * }
 * ```
 */
export class A2ANetworkError extends A2AClientError {
  /**
   * Creates a new network error
   * 
   * @param message - Human-readable error message
   * @param details - Optional additional error details
   */
  constructor(message: string, details?: Record<string, unknown>) {
    super('NETWORK_ERROR', message, details);
    this.name = 'A2ANetworkError';
  }
}

/**
 * Error class for validation errors
 * 
 * This class represents errors that occur when validating input parameters,
 * such as missing required fields, invalid formats, or type mismatches.
 * 
 * @example
 * ```typescript
 * if (!agentId) {
 *   throw new A2AValidationError('Agent ID is required', { parameter: 'agentId' });
 * }
 * 
 * if (typeof timeout !== 'number' || timeout <= 0) {
 *   throw new A2AValidationError('Timeout must be a positive number', {
 *     parameter: 'timeout',
 *     value: timeout
 *   });
 * }
 * ```
 */
export class A2AValidationError extends A2AClientError {
  /**
   * Creates a new validation error
   * 
   * @param message - Human-readable error message
   * @param details - Optional additional error details
   */
  constructor(message: string, details?: Record<string, unknown>) {
    super('VALIDATION_ERROR', message, details);
    this.name = 'A2AValidationError';
  }
}

/**
 * Error class for timeout errors
 * 
 * This class represents errors that occur when an operation takes too long to complete,
 * such as a request that exceeds its timeout limit or a long-running operation that
 * fails to complete in the expected time.
 * 
 * @example
 * ```typescript
 * try {
 *   await Promise.race([
 *     fetch('https://a2a-server.example.com'),
 *     new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout')), 5000))
 *   ]);
 * } catch (error) {
 *   if (error.message === 'Timeout') {
 *     throw new A2ATimeoutError('Request timed out after 5 seconds', {
 *       timeoutMs: 5000,
 *       operation: 'fetch'
 *     });
 *   }
 * }
 * ```
 */
export class A2ATimeoutError extends A2AClientError {
  /**
   * Creates a new timeout error
   * 
   * @param message - Human-readable error message
   * @param details - Optional additional error details
   */
  constructor(message: string, details?: Record<string, unknown>) {
    super('TIMEOUT_ERROR', message, details);
    this.name = 'A2ATimeoutError';
  }
}
