import * as Expires from '../Expires.js';
import * as AcceptPayment from '../internal/AcceptPayment.js';
import * as Fetch from './internal/Fetch.js';
import * as Transport from './Transport.js';
/**
 * Creates a client-side payment handler from an array of methods.
 *
 * Returns a payment handler with a `fetch` function that automatically handles
 * 402 Payment Required responses. By default, also polyfills `globalThis.fetch`.
 *
 * @example
 * ```ts
 * import { Mppx, tempo } from 'mppx/client'
 *
 * const mppx = Mppx.create({
 *   methods: [tempo({ account })],
 * })
 *
 * // Use the returned fetch — handles 402 automatically
 * const res = await mppx.fetch('/resource')
 *
 * // Or use globalThis.fetch (polyfilled by default)
 * const res2 = await fetch('/resource')
 * ```
 */
export function create(config) {
    const { onChallenge, polyfill = true, acceptPaymentPolicy = polyfill && typeof globalThis.location !== 'undefined'
        ? 'same-origin'
        : 'always', transport = Transport.http(), } = config;
    const rawFetch = config.fetch ?? globalThis.fetch;
    const methods = config.methods.flat();
    const acceptPayment = AcceptPayment.resolve(methods, config.paymentPreferences);
    const resolvedOnChallenge = onChallenge;
    const config_fetch = {
        acceptPayment,
        acceptPaymentPolicy,
        ...(config.fetch && { fetch: config.fetch }),
        ...(resolvedOnChallenge && { onChallenge: resolvedOnChallenge }),
        methods,
    };
    const fetch = Fetch.from(config_fetch);
    if (polyfill)
        Fetch.polyfill(config_fetch);
    return {
        fetch,
        rawFetch,
        methods,
        transport,
        async createCredential(response, context, options) {
            const challenges = transport.getChallenges
                ? transport.getChallenges(response)
                : [transport.getChallenge(response)];
            const preferences = resolveChallengePreferences(acceptPayment.entries, options?.acceptPayment);
            const selected = AcceptPayment.selectChallenge(challenges, methods, preferences);
            if (!selected)
                throw new Error(`No method found for challenges: ${challenges.map((challenge) => `${challenge.method}.${challenge.intent}`).join(', ')}. Available: ${methods.map((m) => `${m.name}.${m.intent}`).join(', ')}`);
            const { challenge, method: mi } = selected;
            if (challenge.expires)
                Expires.assert(challenge.expires, challenge.id);
            const parsedContext = mi.context && context !== undefined ? mi.context.parse(context) : undefined;
            return mi.createCredential(parsedContext !== undefined
                ? { challenge, context: parsedContext }
                : { challenge });
        },
    };
}
/**
 * Restores the original `fetch` after `create()` polyfilled it.
 *
 * @example
 * ```ts
 * import { Mppx, tempo } from 'mppx/client'
 *
 * Mppx.create({ methods: [tempo({ account })] })
 *
 * // ... use payment-aware fetch ...
 *
 * Mppx.restore()
 * ```
 */
export function restore() {
    Fetch.restore();
}
function resolveChallengePreferences(fallback, override) {
    if (!override)
        return fallback;
    return typeof override === 'string' ? AcceptPayment.parse(override) : override;
}
//# sourceMappingURL=Mppx.js.map