/**
 * Error definitions for {{pascalCase serviceName}} service.
 * @module @aiox/{{kebabCase serviceName}}/errors
 * @story {{storyId}}
 */

/**
 * Error codes for {{pascalCase serviceName}} service.
 */
export enum {{pascalCase serviceName}}ErrorCode {
  /** Configuration is missing or invalid */
  CONFIGURATION_ERROR = 'CONFIGURATION_ERROR',

  /** Network or connectivity issue */
  NETWORK_ERROR = 'NETWORK_ERROR',

  /** Operation timed out */
  TIMEOUT_ERROR = 'TIMEOUT_ERROR',

  /** Feature not yet implemented */
  NOT_IMPLEMENTED = 'NOT_IMPLEMENTED',

  /** Unknown or unexpected error */
  UNKNOWN_ERROR = 'UNKNOWN_ERROR',

{{#if isApiIntegration}}
  /** API rate limit exceeded */
  RATE_LIMIT_EXCEEDED = 'RATE_LIMIT_EXCEEDED',

  /** API authentication failed */
  AUTHENTICATION_ERROR = 'AUTHENTICATION_ERROR',

  /** API authorization failed */
  AUTHORIZATION_ERROR = 'AUTHORIZATION_ERROR',

  /** API returned an error response */
  API_ERROR = 'API_ERROR',

  /** Invalid API response format */
  INVALID_RESPONSE = 'INVALID_RESPONSE',
{{/if}}
}

/**
 * Custom error class for {{pascalCase serviceName}} service.
 */
export class {{pascalCase serviceName}}Error extends Error {
  /**
   * Error code for programmatic handling.
   */
  public readonly code: {{pascalCase serviceName}}ErrorCode;

  /**
   * Additional error details.
   */
  public readonly details?: Record<string, unknown>;

  /**
   * Original error that caused this error.
   */
  public readonly cause?: Error;

{{#if isApiIntegration}}
  /**
   * HTTP status code (for API errors).
   */
  public readonly statusCode?: number;

  /**
   * Rate limit information (for rate limit errors).
   */
  public readonly rateLimit?: {
    remaining: number;
    reset: number;
  };
{{/if}}

  constructor(
    message: string,
    code: {{pascalCase serviceName}}ErrorCode = {{pascalCase serviceName}}ErrorCode.UNKNOWN_ERROR,
    options?: {
      details?: Record<string, unknown>;
      cause?: Error;
{{#if isApiIntegration}}
      statusCode?: number;
      rateLimit?: { remaining: number; reset: number };
{{/if}}
    }
  ) {
    super(message);
    this.name = '{{pascalCase serviceName}}Error';
    this.code = code;
    this.details = options?.details;
    this.cause = options?.cause;
{{#if isApiIntegration}}
    this.statusCode = options?.statusCode;
    this.rateLimit = options?.rateLimit;
{{/if}}

    // Maintains proper stack trace for where error was thrown
    if (Error.captureStackTrace) {
      Error.captureStackTrace(this, {{pascalCase serviceName}}Error);
    }
  }

  /**
   * Returns a JSON representation of the error.
   */
  toJSON(): Record<string, unknown> {
    return {
      name: this.name,
      code: this.code,
      message: this.message,
      details: this.details,
      cause: this.cause ? { name: this.cause.name, message: this.cause.message } : undefined,
{{#if isApiIntegration}}
      statusCode: this.statusCode,
      rateLimit: this.rateLimit,
{{/if}}
    };
  }
}

/**
 * Factory functions for creating typed errors.
 */
export const {{pascalCase serviceName}}Errors = {
  /**
   * Create a configuration error.
   */
  configurationError(message: string, details?: Record<string, unknown>): {{pascalCase serviceName}}Error {
    return new {{pascalCase serviceName}}Error(message, {{pascalCase serviceName}}ErrorCode.CONFIGURATION_ERROR, { details });
  },

  /**
   * Create a network error.
   */
  networkError(message: string, cause?: Error): {{pascalCase serviceName}}Error {
    return new {{pascalCase serviceName}}Error(message, {{pascalCase serviceName}}ErrorCode.NETWORK_ERROR, { cause });
  },

  /**
   * Create a timeout error.
   */
  timeoutError(message: string, details?: Record<string, unknown>): {{pascalCase serviceName}}Error {
    return new {{pascalCase serviceName}}Error(message, {{pascalCase serviceName}}ErrorCode.TIMEOUT_ERROR, { details });
  },

{{#if isApiIntegration}}
  /**
   * Create a rate limit error.
   */
  rateLimitError(retryAfter: number, rateLimit: { remaining: number; reset: number }): {{pascalCase serviceName}}Error {
    return new {{pascalCase serviceName}}Error(
      `Rate limit exceeded. Retry after ${retryAfter} seconds.`,
      {{pascalCase serviceName}}ErrorCode.RATE_LIMIT_EXCEEDED,
      { statusCode: 429, rateLimit }
    );
  },

  /**
   * Create an authentication error.
   */
  authenticationError(message: string = 'Authentication failed'): {{pascalCase serviceName}}Error {
    return new {{pascalCase serviceName}}Error(message, {{pascalCase serviceName}}ErrorCode.AUTHENTICATION_ERROR, { statusCode: 401 });
  },

  /**
   * Create an authorization error.
   */
  authorizationError(message: string = 'Access denied'): {{pascalCase serviceName}}Error {
    return new {{pascalCase serviceName}}Error(message, {{pascalCase serviceName}}ErrorCode.AUTHORIZATION_ERROR, { statusCode: 403 });
  },

  /**
   * Create an API error from response.
   */
  apiError(statusCode: number, message: string, details?: Record<string, unknown>): {{pascalCase serviceName}}Error {
    return new {{pascalCase serviceName}}Error(message, {{pascalCase serviceName}}ErrorCode.API_ERROR, { statusCode, details });
  },
{{/if}}
};
