import { Head, router } from '@inertiajs/react';
import { Elements, PaymentElement, useElements, useStripe } from '@stripe/react-stripe-js';
import { loadStripe } from '@stripe/stripe-js';
import type { FormEvent } from 'react';
import { useMemo, useState } from 'react';
import { syncBookingPayment } from '@/lib/sync-booking-payment';
import { Alert, AlertDescription } from '@/components/ui/alert';
import { Button } from '@/components/ui/button';

type Props = {
    bookingUuid: string;
    clientSecret: string;
    stripePublishableKey: string;
};

type PaymentFormProps = {
    bookingUuid: string;
};

function ConfirmPaymentForm({ bookingUuid }: PaymentFormProps) {
    const stripe = useStripe();
    const elements = useElements();
    const [error, setError] = useState<string | null>(null);
    const [processing, setProcessing] = useState(false);

    const submit = async (event: FormEvent<HTMLFormElement>) => {
        event.preventDefault();

        if (!stripe || !elements) {
            setError('Stripe is still loading.');

            return;
        }

        setProcessing(true);
        setError(null);

        const returnUrl = `${window.location.origin}/book/complete?booking=${bookingUuid}`;
        const result = await stripe.confirmPayment({
            elements,
            confirmParams: {
                return_url: returnUrl,
            },
            redirect: 'if_required',
        });

        if (result.error) {
            setError(result.error.message ?? 'Payment failed.');
            setProcessing(false);

            return;
        }

        try {
            await syncBookingPayment(`/pay/${bookingUuid}/confirm`);
        } catch (syncError) {
            setError(
                syncError instanceof Error
                    ? syncError.message
                    : 'Payment succeeded but the booking could not be updated.',
            );
            setProcessing(false);

            return;
        }

        router.visit(`/book/complete?booking=${bookingUuid}`);
    };

    return (
        <div className="flex flex-col gap-4">
            <p className="text-sm text-muted-foreground">
                Enter your card details to complete payment securely with Stripe.
            </p>
            <form onSubmit={submit} className="grid gap-4">
                <PaymentElement />
                {error ? (
                    <Alert variant="destructive">
                        <AlertDescription>{error}</AlertDescription>
                    </Alert>
                ) : null}
                <Button type="submit" disabled={processing || !stripe || !elements}>
                    {processing ? 'Processing…' : 'Pay now'}
                </Button>
            </form>
        </div>
    );
}

export default function Step7PaymentConfirm({
    bookingUuid,
    clientSecret,
    stripePublishableKey,
}: Props) {
    const stripePromise = useMemo(
        () => loadStripe(stripePublishableKey),
        [stripePublishableKey],
    );

    return (
        <>
            <Head title="Secure payment" />

            <Elements stripe={stripePromise} options={{ clientSecret }}>
                <ConfirmPaymentForm bookingUuid={bookingUuid} />
            </Elements>
        </>
    );
}
