// src/types/common.ts
function money(value) {
  return typeof value === "string" ? parseFloat(value) || 0 : value;
}
function moneyFromNumber(value) {
  return value;
}
var ZERO = 0;
var SUPPORTED_CURRENCY_CODES = /* @__PURE__ */ new Set([
  "USD",
  "EUR",
  "GBP",
  "JPY",
  "CNY",
  "CHF",
  "CAD",
  "AUD",
  "GHS",
  "NGN",
  "KES",
  "ZAR",
  "XOF",
  "XAF",
  "EGP",
  "TZS",
  "UGX",
  "RWF",
  "ETB",
  "ZMW",
  "BWP",
  "MUR",
  "NAD",
  "MWK",
  "AOA",
  "CDF",
  "GMD",
  "GNF",
  "LRD",
  "SLL",
  "MZN",
  "BIF",
  "INR",
  "BRL",
  "MXN",
  "KRW",
  "TRY",
  "THB",
  "MYR",
  "PHP",
  "IDR",
  "VND",
  "SGD",
  "HKD",
  "TWD",
  "AED",
  "SAR",
  "ILS"
]);
function isSupportedCurrency(code) {
  return SUPPORTED_CURRENCY_CODES.has(code);
}
var warnedCurrencies = /* @__PURE__ */ new Set();
function currencyCode(value) {
  const normalized = value.trim().toUpperCase();
  if (!isSupportedCurrency(normalized) && !warnedCurrencies.has(normalized)) {
    warnedCurrencies.add(normalized);
    console.warn(
      `[Cimplify] Unrecognized currency code "${normalized}". It may not format correctly.`
    );
  }
  return normalized;
}
var ErrorCode = {
  UNKNOWN_ERROR: "UNKNOWN_ERROR",
  NETWORK_ERROR: "NETWORK_ERROR",
  TIMEOUT: "TIMEOUT",
  UNAUTHORIZED: "UNAUTHORIZED",
  FORBIDDEN: "FORBIDDEN",
  NOT_FOUND: "NOT_FOUND",
  VALIDATION_ERROR: "VALIDATION_ERROR",
  CART_EMPTY: "CART_EMPTY",
  CART_EXPIRED: "CART_EXPIRED",
  CART_NOT_FOUND: "CART_NOT_FOUND",
  ITEM_UNAVAILABLE: "ITEM_UNAVAILABLE",
  VARIANT_NOT_FOUND: "VARIANT_NOT_FOUND",
  VARIANT_OUT_OF_STOCK: "VARIANT_OUT_OF_STOCK",
  ADDON_REQUIRED: "ADDON_REQUIRED",
  ADDON_MAX_EXCEEDED: "ADDON_MAX_EXCEEDED",
  CHECKOUT_VALIDATION_FAILED: "CHECKOUT_VALIDATION_FAILED",
  DELIVERY_ADDRESS_REQUIRED: "DELIVERY_ADDRESS_REQUIRED",
  CUSTOMER_INFO_REQUIRED: "CUSTOMER_INFO_REQUIRED",
  QUOTE_NOT_FOUND: "QUOTE_NOT_FOUND",
  QUOTE_EXPIRED: "QUOTE_EXPIRED",
  QUOTE_CONSUMED: "QUOTE_CONSUMED",
  QUOTE_STORAGE_UNAVAILABLE: "QUOTE_STORAGE_UNAVAILABLE",
  QUOTE_VALIDATION_FAILED: "QUOTE_VALIDATION_FAILED",
  PRICE_CHANGED: "PRICE_CHANGED",
  PAYMENT_FAILED: "PAYMENT_FAILED",
  PAYMENT_CANCELLED: "PAYMENT_CANCELLED",
  INSUFFICIENT_FUNDS: "INSUFFICIENT_FUNDS",
  CARD_DECLINED: "CARD_DECLINED",
  INVALID_OTP: "INVALID_OTP",
  OTP_EXPIRED: "OTP_EXPIRED",
  AUTHORIZATION_FAILED: "AUTHORIZATION_FAILED",
  PAYMENT_ACTION_NOT_COMPLETED: "PAYMENT_ACTION_NOT_COMPLETED",
  SLOT_UNAVAILABLE: "SLOT_UNAVAILABLE",
  BOOKING_CONFLICT: "BOOKING_CONFLICT",
  SERVICE_NOT_FOUND: "SERVICE_NOT_FOUND",
  OUT_OF_STOCK: "OUT_OF_STOCK",
  INSUFFICIENT_QUANTITY: "INSUFFICIENT_QUANTITY"
};
var DOCS_ERROR_BASE_URL = "https://docs.cimplify.io/reference/error-codes";
function docsUrlForCode(code) {
  return `${DOCS_ERROR_BASE_URL}#${code.toLowerCase().replace(/_/g, "-")}`;
}
var ERROR_SUGGESTIONS = {
  UNKNOWN_ERROR: "An unexpected error occurred. Capture the request/response payload and retry with exponential backoff.",
  NETWORK_ERROR: "Check the shopper's connection and retry. If this persists, inspect CORS, DNS, and API reachability.",
  TIMEOUT: "The request exceeded the timeout. Retry once, then poll order status before charging again.",
  UNAUTHORIZED: "Authentication is missing or expired. Ensure a valid access token is set and refresh the session if needed.",
  FORBIDDEN: "The key/session lacks permission for this resource. Verify business ownership and API key scope.",
  NOT_FOUND: "The requested resource does not exist or is not visible in this environment.",
  VALIDATION_ERROR: "One or more fields are invalid. Validate required fields and enum values before retrying.",
  CART_EMPTY: "The cart has no items. Redirect back to menu/catalogue and require at least one line item.",
  CART_EXPIRED: "This cart is no longer active. Recreate a new cart and re-add shopper selections.",
  CART_NOT_FOUND: "Cart could not be located. It may have expired or belongs to a different key/location.",
  ITEM_UNAVAILABLE: "The selected item is unavailable at this location/time. Prompt the shopper to pick an alternative.",
  VARIANT_NOT_FOUND: "The requested variant no longer exists. Refresh product data and require re-selection.",
  VARIANT_OUT_OF_STOCK: "The selected variant is out of stock. Show in-stock variants and block checkout for this line.",
  ADDON_REQUIRED: "A required add-on is missing. Ensure required modifier groups are completed before add-to-cart.",
  ADDON_MAX_EXCEEDED: "Too many add-ons were selected. Enforce max selections client-side before submission.",
  CHECKOUT_VALIDATION_FAILED: "Checkout payload failed validation. Verify customer, order type, and address fields are complete.",
  DELIVERY_ADDRESS_REQUIRED: "Delivery orders require an address. Collect and pass address info before processing checkout.",
  CUSTOMER_INFO_REQUIRED: "Customer details are required. Ensure name/email/phone are available before checkout.",
  QUOTE_NOT_FOUND: "Quote could not be found. Refresh pricing and create a new quote before checkout.",
  QUOTE_EXPIRED: "Quote has expired. Re-fetch pricing to generate a new quote with a valid expiry window.",
  QUOTE_CONSUMED: "Quote has already been used. Request a fresh quote to prevent duplicate checkout attempts.",
  QUOTE_STORAGE_UNAVAILABLE: "Quote storage is temporarily unavailable. Retry shortly and avoid charging until quote fetch succeeds.",
  QUOTE_VALIDATION_FAILED: "Cart contents diverged from the locked quote (different items, options, or quantity). Refresh quotes for the affected lines and resubmit.",
  PRICE_CHANGED: "Prices changed since the quote was created. Refresh pricing, show the new total to the shopper, and require explicit confirmation before re-submitting.",
  PAYMENT_FAILED: "Payment provider rejected or failed processing. Show retry/change-method options to the shopper.",
  PAYMENT_CANCELLED: "Payment was cancelled by the shopper or provider flow. Allow a safe retry path.",
  INSUFFICIENT_FUNDS: "Payment method has insufficient funds. Prompt shopper to use another method.",
  CARD_DECLINED: "Card was declined. Ask shopper to retry or switch payment method.",
  INVALID_OTP: "Authorization code is invalid. Let shopper re-enter OTP/PIN and retry.",
  OTP_EXPIRED: "Authorization code expired. Request a new OTP and re-submit authorization.",
  AUTHORIZATION_FAILED: "Additional payment authorization failed. Retry authorization or change payment method.",
  PAYMENT_ACTION_NOT_COMPLETED: "Required payment action was not completed. Resume provider flow and poll for status.",
  SLOT_UNAVAILABLE: "Selected schedule slot is unavailable. Refresh available slots and ask shopper to reselect.",
  BOOKING_CONFLICT: "The requested booking conflicts with an existing reservation. Pick another slot/resource.",
  SERVICE_NOT_FOUND: "Requested service no longer exists. Refresh service catalogue and retry selection.",
  OUT_OF_STOCK: "Inventory is depleted for this item. Remove it or reduce quantity before checkout.",
  INSUFFICIENT_QUANTITY: "Requested quantity exceeds available inventory. Reduce quantity and retry.",
  BUSINESS_ID_REQUIRED: "Business context could not be resolved. Verify the public key and business bootstrap call.",
  INVALID_CART: "Cart is invalid for checkout. Sync cart state, ensure items exist, then retry.",
  ORDER_TYPE_REQUIRED: "Order type is required. Provide one of delivery, pickup, or dine_in before checkout.",
  NO_PAYMENT_ELEMENT: "PaymentElement is required for processCheckout(). Mount it before triggering checkout.",
  PAYMENT_NOT_MOUNTED: "PaymentElement iframe is not mounted. Mount it in the DOM before processCheckout().",
  AUTH_INCOMPLETE: "AuthElement has not completed authentication. Wait for AUTHENTICATED before checkout.",
  AUTH_LOST: "Session was cleared during checkout. Re-authenticate and restart checkout safely.",
  ALREADY_PROCESSING: "Checkout is already in progress. Disable duplicate submits until completion.",
  CHECKOUT_NOT_READY: "Checkout elements are still initializing. Wait for readiness before submit.",
  CANCELLED: "Checkout was cancelled. Preserve cart state and allow shopper to retry.",
  REQUEST_TIMEOUT: "Provider call timed out. Poll payment/order status before issuing another charge attempt.",
  POPUP_BLOCKED: "Browser blocked provider popup. Ask shopper to enable popups and retry.",
  FX_QUOTE_FAILED: "Failed to lock FX quote. Retry currency quote or fallback to base currency."
};
var ERROR_HINTS = Object.fromEntries(
  Object.entries(ERROR_SUGGESTIONS).map(([code, suggestion]) => [
    code,
    {
      docs_url: docsUrlForCode(code),
      suggestion
    }
  ])
);
var CimplifyError = class extends Error {
  constructor(code, message, retryable = false, docs_url, suggestion) {
    super(message);
    this.code = code;
    this.retryable = retryable;
    this.docs_url = docs_url;
    this.suggestion = suggestion;
    this.name = "CimplifyError";
  }
  get userMessage() {
    return this.message;
  }
};
var IdempotencyMismatchError = class extends CimplifyError {
  constructor(message, originalCreatedAt) {
    super("IDEMPOTENCY_MISMATCH", message, false);
    this.originalCreatedAt = originalCreatedAt;
    this.name = "IdempotencyMismatchError";
  }
};
function isCimplifyError(error) {
  return error instanceof CimplifyError;
}
var QUOTE_ERROR_CODES = /* @__PURE__ */ new Set([
  ErrorCode.QUOTE_NOT_FOUND,
  ErrorCode.QUOTE_EXPIRED,
  ErrorCode.QUOTE_CONSUMED,
  ErrorCode.QUOTE_STORAGE_UNAVAILABLE,
  ErrorCode.QUOTE_VALIDATION_FAILED,
  ErrorCode.PRICE_CHANGED
]);
function isQuoteError(error) {
  if (!isCimplifyError(error)) return false;
  return QUOTE_ERROR_CODES.has(error.code);
}
function isQuoteConflictRequiringConsent(error) {
  if (!isCimplifyError(error)) return false;
  return error.code === ErrorCode.PRICE_CHANGED || error.code === ErrorCode.QUOTE_VALIDATION_FAILED;
}
function isIdempotencyMismatchError(error) {
  return error instanceof IdempotencyMismatchError;
}
function getErrorHint(code) {
  return ERROR_HINTS[code];
}
function enrichError(error, options = {}) {
  if (error instanceof IdempotencyMismatchError) {
    return error;
  }
  const hint = getErrorHint(error.code);
  const docsUrl = error.docs_url || hint?.docs_url || docsUrlForCode(error.code || ErrorCode.UNKNOWN_ERROR);
  const suggestion = error.suggestion || hint?.suggestion;
  let message = error.message;
  if (options.isTestMode && !message.includes("cpk_test_")) {
    message = `${message}

\u2139 Your API key is a test-mode key (cpk_test_...). Verify test data/session before retrying.`;
  }
  const enriched = new CimplifyError(error.code, message, error.retryable, docsUrl, suggestion);
  enriched.stack = error.stack;
  return enriched;
}
function isRetryableError(error) {
  if (isCimplifyError(error)) {
    return error.retryable;
  }
  if (error instanceof Error) {
    const msg = error.message.toLowerCase();
    return msg.includes("network") || msg.includes("timeout") || msg.includes("fetch");
  }
  return false;
}

export { CimplifyError, ERROR_HINTS, ErrorCode, IdempotencyMismatchError, ZERO, currencyCode, enrichError, getErrorHint, isCimplifyError, isIdempotencyMismatchError, isQuoteConflictRequiringConsent, isQuoteError, isRetryableError, isSupportedCurrency, money, moneyFromNumber };
