type StripeFactory = (key: string) => StripeLike;

export type StripeLike = {
    elements: (options: Record<string, unknown>) => StripeElements;
    confirmPayment: (options: Record<string, unknown>) => Promise<{
        error?: { message?: string };
        paymentIntent?: { id?: string; status?: string };
        setupIntent?: { id?: string; status?: string };
    }>;
    confirmSetup: (options: Record<string, unknown>) => Promise<{
        error?: { message?: string };
        setupIntent?: { id?: string; status?: string };
    }>;
};

export type StripeElements = {
    create: (name: string, options?: Record<string, unknown>) => StripeElement;
    getElement: (name: string) => StripeElement | null;
    submit: () => Promise<{ error?: { message?: string } }>;
    update: (options: Record<string, unknown>) => void;
};

export type StripeElement = {
    mount: (target: string | HTMLElement) => void;
    unmount: () => void;
    on: (event: string, handler: (event: Record<string, unknown>) => void) => void;
};

declare global {
    interface Window {
        Stripe?: StripeFactory;
    }
}

let loading: Promise<StripeFactory> | null = null;

export function loadStripeJs(): Promise<StripeFactory> {
    if (window.Stripe) {
        return Promise.resolve(window.Stripe);
    }

    if (loading) {
        return loading;
    }

    loading = new Promise((resolve, reject) => {
        const script = document.createElement('script');
        script.src = 'https://js.stripe.com/v3/';
        script.async = true;
        script.onload = () => {
            if (window.Stripe) {
                resolve(window.Stripe);

                return;
            }

            reject(new Error('Stripe.js indisponible'));
        };
        script.onerror = () => reject(new Error('Impossible de charger Stripe.js'));
        document.head.append(script);
    });

    return loading;
}

export function ledgerAppearance(): Record<string, unknown> {
    const style = getComputedStyle(document.documentElement);

    return {
        theme: 'stripe',
        variables: {
            colorPrimary: style.getPropertyValue('--primary').trim() || '#0f172a',
            colorBackground: style.getPropertyValue('--card').trim() || '#ffffff',
            colorText: style.getPropertyValue('--foreground').trim() || '#0f172a',
            colorDanger: style.getPropertyValue('--destructive').trim() || '#b91c1c',
            fontFamily: style.getPropertyValue('--font-sans').trim() || 'inherit',
            borderRadius: '12px',
        },
    };
}
