export type ErrorCode =
  | "BAD_REQUEST"
  | "UNAUTHORIZED"
  | "FORBIDDEN"
  | "NOT_FOUND"
  | "CONFLICT"
  | "RATE_LIMITED"
  | "INTERNAL_ERROR"
  | "DEVICE_UNAUTHORIZED"
  | "DUPLICATE_REQUEST"
  | "TRACE_MISSING"
  | "WEBHOOK_SIGNATURE_INVALID"
  | "TRANSACTION_NOT_FOUND"
  | "PAYMENT_STATUS_INVALID"
  | "DUPLICATE_WEBHOOK"
  | "CALLBACK_PARTNER_DATA_INVALID"
  | "IDEMPOTENCY_MISSING_KEY"
  | "NOTIFICATION_DEVICE_UNAVAILABLE"
  | "NOTIFICATION_NO_ACTIVE_BINDING"
  | "NOTIFICATION_PUBLISH_FAILED"
  | "NOTIFICATION_RETRY_EXHAUSTED"
  | "INVALID_AMOUNT"
  | "DEVICE_NOT_BOUND"
  | "DEVICE_CAPABILITY_NOT_SUPPORTED"
  | "CONFIG_ALREADY_APPLIED";

export interface ApiErrorShape {
  code: ErrorCode;
  message: string;
  details?: Record<string, unknown>;
  request_id: string;
  timestamp: string;
}

export class ApiError extends Error {
  statusCode: number;
  code: ErrorCode;
  details?: Record<string, unknown>;

  constructor(code: ErrorCode, message: string, statusCode = 400, details?: Record<string, unknown>) {
    super(message);
    this.code = code;
    this.statusCode = statusCode;
    this.details = details;
    Error.captureStackTrace(this, this.constructor);
  }
}

export function errorEnvelope(error: ApiError, requestId: string): ApiErrorShape {
  return {
    code: error.code,
    message: error.message,
    details: error.details,
    request_id: requestId,
    timestamp: new Date().toISOString()
  };
}
