export interface PacificaErrorOptions {
  status: number;
  code?: string;
  retryAfterMs?: number;
  payload?: unknown;
}

export class PacificaApiError extends Error {
  readonly status: number;
  readonly code?: string;
  readonly retryAfterMs?: number;
  readonly payload?: unknown;

  constructor(message: string, options: PacificaErrorOptions) {
    super(message);
    this.name = "PacificaApiError";
    this.status = options.status;
    this.code = options.code;
    this.retryAfterMs = options.retryAfterMs;
    this.payload = options.payload;
  }
}

export class PacificaAuthError extends PacificaApiError {
  constructor(message: string, options: PacificaErrorOptions) {
    super(message, { ...options, status: options.status || 401 });
    this.name = "PacificaAuthError";
  }
}

export class PacificaValidationError extends PacificaApiError {
  constructor(message: string, options: PacificaErrorOptions) {
    super(message, options);
    this.name = "PacificaValidationError";
  }
}

export class PacificaRateLimitError extends PacificaApiError {
  constructor(message: string, options: PacificaErrorOptions) {
    super(message, options);
    this.name = "PacificaRateLimitError";
  }
}

export class PacificaUnavailableError extends PacificaApiError {
  constructor(message: string, options: PacificaErrorOptions) {
    super(message, options);
    this.name = "PacificaUnavailableError";
  }
}

export function buildPacificaError(
  status: number,
  rawText: string,
  json?: any,
  retryAfter?: number
): PacificaApiError {
  const code =
    json?.code ??
    json?.errorCode ??
    json?.error_code ??
    json?.error;

  const rawMessage =
    json?.message ??
    json?.errorMessage ??
    json?.error ??
    rawText;

  const message = rawMessage || `Pacifica API error (status ${status})`;

  const options: PacificaErrorOptions = {
    status,
    code,
    retryAfterMs: retryAfter,
    payload: json ?? rawText
  };

  if (status === 401 || status === 403 || code === "UNAUTHENTICATED") {
    return new PacificaAuthError(message, options);
  }
  if (status === 429 || code === "RATE_LIMITED") {
    return new PacificaRateLimitError(message, options);
  }
  if (status === 400 || code === "INVALID_SIZE" || code === "POST_ONLY_WOULD_CROSS") {
    return new PacificaValidationError(message, options);
  }
  if (status >= 500) {
    return new PacificaUnavailableError(message, options);
  }

  return new PacificaApiError(message, options);
}
