import { logger } from "../util/logger.js";
import { importPeer } from "../util/peer.js";
import { withExponentialBackoff } from "../util/retry.js";
export async function createStripeClient(options = {}) {
    const { default: Stripe } = await importPeer(import("stripe"), "Stripe resources");
    let apiKey;
    if (options.apiKey) {
        apiKey =
            typeof options.apiKey === "string"
                ? options.apiKey
                : options.apiKey.unencrypted;
    }
    else {
        const envApiKey = process.env.STRIPE_API_KEY;
        if (!envApiKey) {
            throw new Error("Stripe API key is required. Provide it via the apiKey parameter or set the STRIPE_API_KEY environment variable.");
        }
        apiKey = envApiKey;
    }
    const stripe = new Stripe(apiKey);
    return createStripeProxy(stripe);
}
export function handleStripeDeleteError(error, resourceType, resourceId) {
    if (error?.code === "resource_missing" || error?.status === 404) {
        logger.log(`${resourceType} ${resourceId || "unknown"} not found during deletion (already deleted)`);
        return;
    }
    logger.error(`Error deleting ${resourceType} ${resourceId || "unknown"}:`, error);
    throw error;
}
export function isStripeConflictError(error) {
    return error?.status === 409 || error?.statusCode === 409;
}
/**
 * Creates a proxy that wraps Stripe API calls with retry logic
 */
function createStripeProxy(stripe) {
    // Cache for proxied resources to avoid creating new proxies for the same resource
    const resourceProxyCache = new Map();
    return new Proxy(stripe, {
        get(target, prop, receiver) {
            const value = Reflect.get(target, prop, receiver);
            // If it's not a property we want to proxy, return as-is
            if (typeof prop !== "string" ||
                typeof value !== "object" ||
                value === null) {
                return value;
            }
            // Check if this looks like a Stripe resource (has methods like create, retrieve, etc.)
            const hasStripeResourceMethods = value &&
                typeof value === "object" &&
                (typeof value.create === "function" ||
                    typeof value.retrieve === "function" ||
                    typeof value.list === "function" ||
                    typeof value.update === "function" ||
                    typeof value.del === "function");
            if (!hasStripeResourceMethods) {
                return value;
            }
            // Return cached proxy if it exists
            if (resourceProxyCache.has(prop)) {
                return resourceProxyCache.get(prop);
            }
            // Create a new proxy for this resource
            const resourceProxy = new Proxy(value, {
                get(resourceTarget, methodName, resourceReceiver) {
                    const method = Reflect.get(resourceTarget, methodName, resourceReceiver);
                    // If it's not a function, return as-is
                    if (typeof method !== "function") {
                        return method;
                    }
                    // Wrap the method with retry logic
                    return (...args) => withStripeRetry(() => method.apply(resourceTarget, args));
                },
            });
            // Cache the proxy
            resourceProxyCache.set(prop, resourceProxy);
            return resourceProxy;
        },
    });
}
/**
 * Determines if a Stripe error should trigger a retry
 */
function isStripeRetryableError(error) {
    return (error?.raw?.statusCode === 429 ||
        error?.code === "rate_limit" ||
        error?.type === "rate_limit_error");
}
/**
 * Wraps a Stripe API operation with retry logic for rate limiting
 */
async function withStripeRetry(operation, maxAttempts = 5, initialDelayMs = 1000) {
    return withExponentialBackoff(operation, isStripeRetryableError, maxAttempts, initialDelayMs);
}
//# sourceMappingURL=client.js.map