/**
 * Custom error class for Freebit API errors
 */
export class FreebitError extends Error {
  public readonly resultCode?: string | number;
  public readonly statusCode?: string | number;
  public readonly statusMessage?: string;

  constructor(
    message: string,
    resultCode?: string | number,
    statusCode?: string | number,
    statusMessage?: string
  ) {
    super(message);
    this.name = "FreebitError";
    this.resultCode = resultCode;
    this.statusCode = statusCode;
    this.statusMessage = statusMessage;

    // Maintains proper stack trace for where our error was thrown (only available on V8)
    if (Error.captureStackTrace) {
      Error.captureStackTrace(this, FreebitError);
    }
  }

  /**
   * Check if error indicates authentication failure
   */
  isAuthError(): boolean {
    return (
      this.resultCode === "401" ||
      this.statusCode === "401" ||
      this.message.toLowerCase().includes("authentication") ||
      this.message.toLowerCase().includes("unauthorized")
    );
  }

  /**
   * Check if error indicates rate limiting
   */
  isRateLimitError(): boolean {
    return (
      this.resultCode === "429" ||
      this.statusCode === "429" ||
      this.message.toLowerCase().includes("rate limit") ||
      this.message.toLowerCase().includes("too many requests")
    );
  }

  /**
   * Check if error is retryable
   */
  isRetryable(): boolean {
    const retryableCodes = ["500", "502", "503", "504", "408", "429"];
    return (
      retryableCodes.includes(String(this.resultCode)) ||
      retryableCodes.includes(String(this.statusCode)) ||
      this.message.toLowerCase().includes("timeout") ||
      this.message.toLowerCase().includes("network")
    );
  }

  /**
   * Get user-friendly error message
   */
  getUserFriendlyMessage(): string {
    if (this.isAuthError()) {
      return "SIM service is temporarily unavailable. Please try again later.";
    }

    if (this.isRateLimitError()) {
      return "Service is busy. Please wait a moment and try again.";
    }

    if (this.message.toLowerCase().includes("account not found")) {
      return "SIM account not found. Please contact support to verify your SIM configuration.";
    }

    if (this.message.toLowerCase().includes("timeout")) {
      return "SIM service request timed out. Please try again.";
    }

    // Specific error codes
    if (this.resultCode === "215" || this.statusCode === "215") {
      return "Plan change failed. This may be due to: (1) Account has existing scheduled operations, (2) Invalid plan code for this account, (3) Account restrictions. Please check the Freebit Partner Tools for account status or contact support.";
    }

    if (this.resultCode === "381" || this.statusCode === "381") {
      return "Network type change rejected. The current plan does not allow switching to the requested contract line. Adjust the plan first or contact support.";
    }

    if (this.resultCode === "382" || this.statusCode === "382") {
      return "Network type change rejected because the contract line is not eligible for modification at this time. Please verify the SIM's status in Freebit before retrying.";
    }

    return "SIM operation failed. Please try again or contact support.";
  }
}
