import { Appearance, StripeElementLocale, Stripe } from '@stripe/stripe-js';
import { ChargeResult } from '@platform-modules/billing';
import * as react from 'react';
import { ReactNode } from 'react';

interface StripePaymentProviderProps {
    /** Stripe publishable key (pk_test_… / pk_live_…). PUBLIC — safe in the client bundle. */
    publishableKey: string;
    /**
     * Per-PaymentIntent client secret from checkout start (billing ChargeResult.requires_client_action).
     * Client-safe. This is the PaymentIntent IDENTITY: the provider internally keys the Elements group
     * to it, so passing a NEW clientSecret auto-remounts the card field for the new intent — pass it
     * as a normal prop, no manual `key=` needed. A change clears the card field (correct: card data
     * lives in Stripe's iframe and is intrinsically unpreservable across a new intent).
     */
    clientSecret: Extract<ChargeResult, {
        kind: 'requires_client_action';
    }>['clientSecret'];
    /** Optional Elements appearance (token-driven, see spec §6). */
    appearance?: Appearance;
    /** Optional Elements locale. */
    locale?: StripeElementLocale;
    /** TEST-ONLY seam — a resolved/stub Stripe so jsdom tests never hit the network. */
    stripeOverride?: PromiseLike<Stripe | null>;
    children: ReactNode;
}
declare function StripePaymentProvider({ publishableKey, clientSecret, appearance, locale, stripeOverride, children, }: StripePaymentProviderProps): JSX.Element;

/**
 * PSP-neutral card-field mount. Under StripePaymentProvider → renders Stripe <PaymentElement>.
 * Propless v1 — appearance/locale flow through the provider (§2). No className escape hatch
 * (token discipline enforced by mod-ui-enforcement on the impl).
 */
declare function PaymentElement(): JSX.Element;

/** Config / mount / secret-guard failure (programming or wiring error). */
declare class PaymentProviderError extends Error {
    readonly name = "PaymentProviderError";
    constructor(message: string);
}
/** A payment confirmation failure (declined card, etc.). NOT a throw — returned in PaymentConfirmResult. */
declare class PaymentConfirmError extends Error {
    readonly name = "PaymentConfirmError";
    /** The PSP's own error-code string, passed through verbatim (Stripe error.code). A plain string. */
    readonly code: string;
    constructor(message: string, code: string);
}
/** Structural guard — keys on name + Error shape, NEVER instanceof (cross-package dedup-safe). */
declare function isPaymentProviderError(e: unknown): e is PaymentProviderError;
declare function isPaymentConfirmError(e: unknown): e is PaymentConfirmError;

declare function usePaymentElement(): {
    ready: boolean;
    error: PaymentProviderError | null;
};

/** Result of a client-side confirm. Neutral — no PSP type leaks. */
type PaymentConfirmResult = {
    /**
     * Client-side success ONLY — NOT settlement. The order is fulfilled by the SERVER webhook
     * (billing.ingestWebhook → checkout settlement). Navigate to a server-truth order-status screen;
     * NEVER render fulfillment ('download ready', 'access granted') off this client result — the
     * webhook may lag.
     */
    kind: 'succeeded';
} | {
    kind: 'requires_redirect';
} | {
    kind: 'error';
    error: PaymentConfirmError;
};
interface ConfirmPaymentOptions {
    /** URL the PSP redirects back to for redirect-based methods / 3DS fallback. REQUIRED by every PSP confirm. */
    returnUrl: string;
}
/** The neutral context a PSP provider populates. */
interface PaymentUiContextValue {
    /** True once the PSP element is mounted + ready to accept input. */
    ready: boolean;
    /** Confirm the payment client-side. Neutral result; PSP-specific confirm lives in the provider. */
    confirm: (opts: ConfirmPaymentOptions) => Promise<PaymentConfirmResult>;
    /** Set if the PSP element failed to initialise (load/config error). */
    error: PaymentProviderError | null;
}
/** null default → hooks throw "outside provider" rather than read a stale value. */
declare const PaymentUiContext: react.Context<PaymentUiContextValue | null>;

declare function useConfirmPayment(): {
    confirm: (opts: ConfirmPaymentOptions) => Promise<PaymentConfirmResult>;
    /**
     * Client-side success ONLY — NOT settlement. Fulfillment requires the server webhook;
     * navigate to server-truth order status, never render fulfillment off `succeeded` alone.
     */
    status: 'idle' | 'confirming' | 'succeeded' | 'error';
    error: PaymentConfirmError | null;
};

export { type ConfirmPaymentOptions, PaymentConfirmError, type PaymentConfirmResult, PaymentElement, PaymentProviderError, PaymentUiContext, type PaymentUiContextValue, StripePaymentProvider, type StripePaymentProviderProps, isPaymentConfirmError, isPaymentProviderError, useConfirmPayment, usePaymentElement };
