declare global {
	interface Window {
		wco?: {
			injected: true;
			listening: boolean;
			frames: Map<HTMLIFrameElement, () => void>;
			identifiedFrames: Map<string, HTMLIFrameElement>;
			availableCurrencies: Map<string, WhopCheckoutCurrenciesAvailable>;
			submit: (
				identifier: string,
				data?: WhopCheckoutSubmitDetails,
			) => Promise<void>;
			getEmail: (identifier: string, timeout?: number) => Promise<string>;
			setEmail: (
				identifier: string,
				email: string,
				timeout?: number,
			) => Promise<void>;
			getAddress: (
				identifier: string,
				timeout?: number,
			) => Promise<{
				address: WhopCheckoutAddress;
				isComplete: boolean;
			}>;
			setAddress: (
				identifier: string,
				address: WhopCheckoutAddress,
				timeout?: number,
			) => Promise<void>;
			setDisplayCurrency: (
				identifier: string,
				currency: string,
				timeout?: number,
			) => Promise<void>;
			getAvailableCurrencies: (
				identifier: string,
			) => WhopCheckoutCurrenciesAvailable | null;
		};
		Plaid?: Plaid;
	}
}

type Plaid = {
	create(options: {
		token: string;
		onSuccess: (public_token: string) => void;
		onExit: (
			err: {
				error_type: string;
				error_code: string;
				error_message: string;
				display_message: string;
			} | null,
		) => void;
	}): {
		open(): void;
		destroy(): void;
	};
};

type WhopCheckoutSubmitDetails = Record<never, never>;

type WhopCheckoutAddress = {
	name: string;
	country: string;
	line1: string;
	line2?: string;
	city: string;
	state: string;
	postalCode: string;
};

declare global {
	// oxlint-disable-next-line no-var
	var PaymentRequest: {
		prototype: PaymentRequest;
		new (
			methodData: PaymentMethodData[],
			details: PaymentDetailsInit,
			options?: PaymentOptions,
		): PaymentRequest;
	};

	interface Window {
		PaymentRequest: {
			prototype: PaymentRequest;
			new (
				methodData: PaymentMethodData[],
				details: PaymentDetailsInit,
				options?: PaymentOptions,
			): PaymentRequest;
		};
	}

	interface PaymentOptions {
		requestPayerName?: boolean;
		requestBillingAddress?: boolean;
		requestPayerEmail?: boolean;
		requestPayerPhone?: boolean;
		requestShipping?: boolean;
		shippingType?: "shipping" | "delivery" | "pickup";
	}

	interface ApplyPayPaymentRequestPaymentOptions {
		requestPayerName?: boolean;
		requestBillingAddress?: boolean;
		requestPayerEmail?: boolean;
		requestPayerPhone?: boolean;
		requestShipping?: boolean;
		shippingType?: "shipping" | "delivery" | "pickup";
	}

	interface PaymentRequest {
		/**
		 * Apple Pay–specific event fired when Apple Pay
		 * needs merchant validation.
		 */
		onmerchantvalidation?: (event: ApplePayMerchantValidationEvent) => void;

		/**
		 * Apple Pay–specific event fired when the user changes
		 * payment method details (e.g., coupon code).
		 */
		onpaymentmethodchange?: (event: ApplePayPaymentMethodChangeEvent) => void;

		/**
		 * Apple Pay–specific event fired when the user changes
		 * shipping option (if you requested shipping).
		 */
		onshippingoptionchange?: (event: ApplePayShippingOptionChangeEvent) => void;

		/**
		 * Apple Pay–specific event fired when the user changes
		 * shipping address (if you requested shipping).
		 */
		onshippingaddresschange?: (
			event: ApplePayShippingAddressChangeEvent,
		) => void;
	}

	/**
	 * The event object passed to onmerchantvalidation.
	 */
	interface ApplePayMerchantValidationEvent extends Event {
		complete: (
			merchantSession:
				| ApplePayMerchantSession
				| Promise<ApplePayMerchantSession>,
		) => void;
		methodName: string;
		validationURL: string;
	}

	interface ApplePayPaymentContact {
		addressLines: string[];
		administrativeArea: string;
		country: string;
		countryCode: string;
		familyName: string;
		givenName: string;
		locality: string;
		phoneticFamilyName: string;
		phoneticGivenName: string;
		postalCode: string;
		subAdministrativeArea: string;
		subLocality: string;
	}

	/**
	 * The event object passed to onpaymentmethodchange.
	 * For example, you may check `event.methodDetails.couponCode`.
	 */
	interface ApplePayPaymentMethodChangeEvent extends Event {
		methodDetails?:
			| {
					type: string;
					billingContact: ApplePayPaymentContact;
			  }
			| {
					couponCode: string;
			  };
		updateWith: (
			details: PaymentDetailsUpdate | Promise<PaymentDetailsUpdate>,
		) => void;
	}

	interface ApplePayShippingOptionChangeEvent extends Event {
		updateWith: (details: PaymentDetailsUpdate) => void;
	}

	interface ApplePayShippingAddressChangeEvent extends Event {
		updateWith: (details: PaymentDetailsUpdate) => void;
	}

	/**
	 * A helper interface if you need to pass dynamic updates to `updateWith()`.
	 * This extends PaymentDetails with extra optional fields that Safari may expect.
	 */
	interface PaymentDetailsUpdate extends PaymentDetails {
		error?: string;
		shippingOptions?: PaymentShippingOption[];
		modifiers?: PaymentDetailsModifier[];
	}

	// Add this new interface for the merchant session
	interface ApplePayMerchantSession {
		merchantIdentifier: string;
		merchantSessionIdentifier: string;
		nonce: string;
		domainName: string;
		displayName: string;
		signature: string;
		epoch: string;
		expiresAt: number;
	}
}

type WhopCheckoutState = "loading" | "ready" | "disabled";
type WhopExpressButtonMethod = "apple-pay" | "whop-pay";
type WhopExpressButtonRendered = "apple-pay" | "google-pay" | "whop-pay" | "none";
type WhopExpressMethodResolved = {
    rendered: WhopExpressButtonRendered;
};
type WhopCheckoutPromoCode = {
    amount: number;
    code: string;
    currency: string;
    duration: string;
    intervals: number;
    type: string;
};
type WhopCheckoutCurrenciesAvailable = {
    base_currency: string;
    optional_currency: string | null;
    current_currency: string;
    exchange_rate: number | null;
};
type WhopCheckoutCurrencyChanged = {
    currency: string;
    exchange_rate: number | null;
};
type WhopCheckoutPaymentError = {
    message: string;
    code?: string;
};
type EmbeddedCheckoutBaseEvent<T extends Record<string, unknown>> = {
    __scope: "whop-embedded-checkout";
    event_id: string;
} & T;
type PaymentRequestCreateRequest = EmbeddedCheckoutBaseEvent<{
    event: "payment-request-create-request";
    method_data: PaymentMethodData[];
    details: PaymentDetailsInit;
    options?: PaymentOptions;
}>;
type PaymentRequestUpdateRequest = EmbeddedCheckoutBaseEvent<{
    event: "payment-request-update-request";
    id: string;
    method_data?: PaymentMethodData[];
    details?: PaymentDetailsInit;
    options?: PaymentOptions;
    active?: boolean;
}>;
type PaymentRequestEventResult = EmbeddedCheckoutBaseEvent<{
    event: "payment-request-event-result";
} & ({
    ok: true;
    details: PaymentDetailsUpdate;
} | {
    ok: false;
    error: string;
})>;
type PaymentRequestMerchantValidationResult = EmbeddedCheckoutBaseEvent<{
    event: "payment-request-merchant-validation-result";
} & ({
    ok: true;
    merchantSession: ApplePayMerchantSession;
} | {
    ok: false;
    error: string;
})>;
type PlaidTokenRequest = EmbeddedCheckoutBaseEvent<{
    event: "plaid-token-request";
    token: string;
}>;
type PlaidReadyEvent = EmbeddedCheckoutBaseEvent<{
    event: "plaid-ready";
}>;
type WhopCheckoutMessage = {
    event: "resize";
    height: number;
} | {
    event: "center";
} | {
    event: "complete";
    receipt_id?: string;
    setup_intent_id?: string;
    plan_id: string;
} | {
    event: "state";
    state: WhopCheckoutState;
} | {
    event: "get-email-result";
    email: string;
    event_id: string;
} | {
    event: "set-email-result";
    ok: true;
    error?: never;
    event_id: string;
} | {
    event: "set-email-result";
    ok: false;
    error: string;
    event_id: string;
} | {
    event: "set-address-result";
    ok: true;
    error?: never;
    event_id: string;
} | {
    event: "set-address-result";
    ok: false;
    error: string;
    event_id: string;
} | {
    event: "get-address-result";
    ok: true;
    address: WhopCheckoutAddress;
    is_complete: boolean;
    event_id: string;
} | {
    event: "get-address-result";
    ok: false;
    error: string;
    event_id: string;
} | {
    event: "address-validation-error";
    error_message: string;
    error_code: string;
} | ({
    event: "payment-error";
} & WhopCheckoutPaymentError) | {
    event: "promo-code-changed";
    promoCode: WhopCheckoutPromoCode | null;
} | {
    event: "identity-captured";
    email?: string;
    user_id?: string;
} | ({
    event: "currencies-available";
} & WhopCheckoutCurrenciesAvailable) | ({
    event: "currency-changed";
} & WhopCheckoutCurrencyChanged) | {
    event: "set-display-currency-result";
    ok: true;
    currency: string;
    event_id: string;
} | {
    event: "set-display-currency-result";
    ok: false;
    error: string;
    event_id: string;
} | ({
    event: "express-method-resolved";
} & WhopExpressMethodResolved) | {
    event: "express-loading";
    loading: boolean;
} | {
    event: "request-overlay";
    channelId: string;
} | {
    event: "request-requirement-overlay";
    channelId: string;
    /**
     * Optional pre-built URL the source iframe wants opened, so its theme /
     * accent color / other search params can flow through to the
     * requirement iframe. The host validates same-origin + path before
     * using it; an invalid or missing value falls back to a URL built by
     * `getRequirementOverlayIframeUrl`. The source iframe is responsible
     * for stripping any `secret` — the session is bridged via BroadcastChannel.
     */
    iframeSrc?: string;
} | {
    event: "close-overlay";
    channelId?: string;
} | PaymentRequestMerchantValidationResult | PaymentRequestUpdateRequest | PaymentRequestCreateRequest | PaymentRequestEventResult | PlaidTokenRequest | PlaidReadyEvent;
declare function isWhopCheckoutMessage(event: MessageEvent<unknown>): event is MessageEvent<WhopCheckoutMessage>;

/**
 * Structural subset of `createOverlayHost`'s return value (see overlay-host.ts)
 * — declared inline to keep util.ts free of a circular import. When an
 * `overlayHost` is supplied, `onWhopCheckoutMessage` intercepts the host-side
 * overlay events centrally, the same way it already intercepts payment-request
 * and plaid. This is what makes overlay handling un-driftable across mount
 * paths: callers can't forget the events because they're handled here and
 * type-excluded from the callback below.
 */
interface OverlayMessageHandler {
    handleOverlayRequest(message: {
        event: "request-overlay";
        channelId: string;
    } | {
        event: "request-requirement-overlay";
        channelId: string;
        iframeSrc?: string;
    }): void;
    handleCloseOverlay(message: {
        channelId?: string;
    }): void;
}
declare function onWhopCheckoutMessage(iframe: HTMLIFrameElement, callback: (message: Exclude<WhopCheckoutMessage, Extract<WhopCheckoutMessage, {
    event: "payment-request-create-request" | "payment-request-update-request" | "plaid-token-request" | "plaid-ready" | "request-overlay" | "request-requirement-overlay";
}>>) => void, overlayHost?: OverlayMessageHandler): () => void;
declare function setEmail(frame: HTMLIFrameElement, email: string, timeout?: number): Promise<void>;
declare function getEmail(frame: HTMLIFrameElement, timeout?: number): Promise<string>;
declare function setAddress(frame: HTMLIFrameElement, address: WhopCheckoutAddress, timeout?: number): Promise<void>;
declare function setDisplayCurrency(frame: HTMLIFrameElement, currency: string, timeout?: number): Promise<void>;
declare function getAddress(frame: HTMLIFrameElement, timeout?: number): Promise<{
    address: WhopCheckoutAddress;
    isComplete: boolean;
}>;
declare function submitCheckoutFrame(frame: HTMLIFrameElement, _data?: WhopCheckoutSubmitDetails): Promise<void>;
declare function parseSetupFutureUsage(val?: string): "off_session" | undefined;

interface WhopEmbeddedCheckoutStyleOptions {
    container?: {
        paddingTop?: number | string;
        paddingBottom?: number | string;
        paddingY?: number | string;
        paddingLeft?: number | string;
        paddingRight?: number | string;
        paddingX?: number | string;
    };
}
interface WhopEmbeddedCheckoutPrefillOptions {
    email?: string;
    /**
     * **Optional** - The buyer's billing address to seed the form with. The
     * buyer can still edit it before paying.
     */
    address?: Partial<WhopCheckoutAddress>;
    /**
     * **Optional** - The buyer's shipping address to seed the form with. Only
     * relevant when the plan collects a shipping address. The buyer can still
     * edit it before paying.
     */
    shippingAddress?: Partial<WhopCheckoutAddress>;
}
interface WhopEmbeddedCheckoutThemeOptions {
    accentColor?: string;
    highContrast?: boolean;
    backgroundColor?: string;
    borderRadius?: number | string;
}
type WhopEmbeddedCheckoutEnvironment = "production" | "sandbox";
declare function isWhopEmbeddedCheckoutEnvironment(environment: unknown): environment is WhopEmbeddedCheckoutEnvironment;
declare function toWhopEmbeddedCheckoutEnvironment(environment: unknown): WhopEmbeddedCheckoutEnvironment;
declare function getEmbeddedCheckoutIframeUrl(planId?: string, theme?: "light" | "dark" | "system", sessionId?: string, origin?: string, hidePrice?: boolean, skipRedirect?: boolean, utm?: Record<string, string | string[]>, styles?: WhopEmbeddedCheckoutStyleOptions, prefill?: WhopEmbeddedCheckoutPrefillOptions, themeOptions?: WhopEmbeddedCheckoutThemeOptions, hideSubmitButton?: boolean, hideTermsAndConditions?: boolean, hideEmail?: boolean, disableEmail?: boolean, hideAddressForm?: boolean, affiliateCode?: string, setupFutureUsage?: "off_session", paymentRedirectUrl?: string, stateId?: string, promoCode?: string, environment?: WhopEmbeddedCheckoutEnvironment, wuid?: string, adaptivePricing?: boolean, collectPhoneNumbers?: boolean, locale?: string): string;
/**
 * Builds the iframe URL for the express checkout button surface.
 *
 * Intentionally narrower than `getEmbeddedCheckoutIframeUrl` — the express
 * button cannot render `hide-*`, `disable-*`, or `style-*` controls and
 * doesn't accept a `data-whop-checkout-session` (sessions are minted
 * server-side and kept on the iframe origin, never travelling through
 * host JS).
 */
declare function getExpressButtonIframeUrl(opts: {
    planId?: string;
    checkoutConfigurationId?: string;
    paymentRedirectUrl: string;
    theme?: "light" | "dark" | "system";
    origin?: string;
    utm?: Record<string, string | string[]>;
    prefill?: WhopEmbeddedCheckoutPrefillOptions;
    themeOptions?: WhopEmbeddedCheckoutThemeOptions;
    affiliateCode?: string;
    stateId?: string;
    promoCode?: string;
    environment?: WhopEmbeddedCheckoutEnvironment;
    wuid?: string;
    adaptivePricing?: boolean;
    methods?: readonly string[];
    setupFutureUsage?: "off_session";
    skipRedirect?: boolean;
    locale?: string;
}): string;
/**
 * Builds the iframe URL for a delegated requirement overlay. The route is
 * static — the only thing it needs is the BroadcastChannel id that the
 * requirement iframe uses to talk to the parent embed that originated the
 * request (the session itself is pushed across the channel, not the URL).
 */
declare function getRequirementOverlayIframeUrl(opts: {
    channelId: string;
    theme?: "light" | "dark" | "system";
    origin?: string;
    environment?: WhopEmbeddedCheckoutEnvironment;
    locale?: string;
}): string;
/**
 * Builds the iframe URL for the overlay loader. Carries only the
 * BroadcastChannel id, theme, and environment — the session id is
 * negotiated cross-iframe (same-origin) and never travels through host
 * JS or this URL.
 */
declare function getOverlayLoaderIframeUrl(opts: {
    channelId: string;
    theme?: "light" | "dark" | "system";
    origin?: string;
    environment?: WhopEmbeddedCheckoutEnvironment;
    locale?: string;
}): string;
declare const EMBEDDED_CHECKOUT_IFRAME_SANDBOX_LIST: string[];
declare const EMBEDDED_CHECKOUT_IFRAME_ALLOW_STRING = "document-domain; execution-while-not-rendered; execution-while-out-of-viewport; payment; paymentRequest; sync-script;";
declare function firePixelIdentify(data: {
    email?: string;
    user_id?: string;
}): void;
declare function getUtmFromCurrentUrl(): Record<string, string | string[]>;
/**
 * Inject the Whop pixel tracking SDK for a given plan / checkout config.
 * No-ops if the SDK or its script tag is already present.
 */
declare function injectPixel(planIdOrCheckoutConfigId: string): void;

export { getRequirementOverlayIframeUrl as A, getOverlayLoaderIframeUrl as B, EMBEDDED_CHECKOUT_IFRAME_ALLOW_STRING as C, firePixelIdentify as D, EMBEDDED_CHECKOUT_IFRAME_SANDBOX_LIST as E, getUtmFromCurrentUrl as F, injectPixel as G, type WhopCheckoutSubmitDetails as W, type WhopCheckoutAddress as a, type WhopCheckoutCurrenciesAvailable as b, type WhopCheckoutState as c, type WhopCheckoutPaymentError as d, type WhopCheckoutPromoCode as e, type WhopCheckoutCurrencyChanged as f, type WhopEmbeddedCheckoutStyleOptions as g, type WhopEmbeddedCheckoutPrefillOptions as h, type WhopEmbeddedCheckoutEnvironment as i, type WhopExpressButtonMethod as j, type WhopExpressButtonRendered as k, isWhopCheckoutMessage as l, type WhopCheckoutMessage as m, getEmail as n, onWhopCheckoutMessage as o, setAddress as p, setDisplayCurrency as q, getAddress as r, setEmail as s, submitCheckoutFrame as t, parseSetupFutureUsage as u, type WhopEmbeddedCheckoutThemeOptions as v, isWhopEmbeddedCheckoutEnvironment as w, toWhopEmbeddedCheckoutEnvironment as x, getEmbeddedCheckoutIframeUrl as y, getExpressButtonIframeUrl as z };
