/**
 * BrickError - Type-safe class for custom errors from native modules.
 * Matches the structure of iOS/Android BrickError.
 */
export class BrickError extends Error {
  /** Error code (same as error.name) */
  readonly code: string;

  /** Additional properties (e.g., amount, currency) */
  readonly userInfo: Record<string, unknown>;

  /** Name of the module where the error occurred */
  readonly moduleName?: string;

  constructor(
    message: string,
    code: string,
    userInfo: Record<string, unknown> = {},
    moduleName?: string
  ) {
    super(message);
    this.name = code;
    this.code = code;
    this.userInfo = userInfo;
    this.moduleName = moduleName;
  }

  /**
   * Type guard to check if an error object is a BrickError.
   * @param error - The error object to check
   * @returns true if the error is a BrickError
   */
  static isBrickError(error: unknown): error is BrickError {
    return (
      error instanceof Error &&
      typeof (error as any).code === "string" &&
      typeof (error as any).userInfo === "object" &&
      (error as any).userInfo !== null
    );
  }

  /**
   * Converts a general error object to a BrickError.
   * @param error - The error object to convert
   * @param moduleName - Name of the module where the error occurred
   * @returns A BrickError instance
   */
  static from(error: unknown, moduleName?: string): BrickError {
    if (error instanceof BrickError) {
      // Update moduleName if provided
      if (moduleName && !error.moduleName) {
        return new BrickError(error.message, error.code, error.userInfo, moduleName);
      }
      return error;
    }

    if (BrickError.isBrickError(error)) {
      return new BrickError(
        error.message,
        error.code,
        error.userInfo,
        moduleName || (error as any).moduleName
      );
    }

    if (error instanceof Error) {
      const anyError = error as any;
      return new BrickError(
        error.message,
        anyError.code || anyError.name || "UNKNOWN_ERROR",
        anyError.userInfo || {},
        moduleName || anyError.moduleName
      );
    }

    return new BrickError(String(error), "UNKNOWN_ERROR", {}, moduleName);
  }
}
