'use client';

import React, { FC, useEffect, useState } from 'react';
import type { StripeError } from '@stripe/stripe-js';
import {
    useStripe,
    useElements,
    PaymentElement,
    Elements,
} from '@stripe/react-stripe-js';
import { Form, Button, message } from 'antd';
import getStripe from '../../utils/get-stripe';
import { createPaymentIntent} from '../../actions/stripe';
import { Payment } from '../../types/payment';
import { i18nText } from '../../i18nKeys';
import { WithError } from '../view/WithError';

type PaymentFormProps = {
    amount: number,
    sessionId?: string,
    locale: string
}

type PaymentInfo = 'initial' | 'error' | 'processing' | 'requires_payment_method' | 'requires_confirmation' | 'requires_action' | 'succeeded';

const PaymentStatus = ({ status }: { status?: PaymentInfo }) => {
    switch (status) {
        case 'processing':
        case 'requires_payment_method':
        case 'requires_confirmation':
            return <h2>Processing...</h2>;

        case 'requires_action':
            return <h2>Authenticating...</h2>;

        case 'succeeded':
            return <h2>Payment Succeeded</h2>;

        default:
            return null;
    }
};

export const CheckoutForm: FC<PaymentFormProps> = ({ amount, sessionId, locale }) => {
    const [form] = Form.useForm<Payment>();
    const formAmount = Form.useWatch('amount', form);
    const [paymentType, setPaymentType] = useState<string>('');
    const [payment, setPayment] = useState<{
        status: PaymentInfo
    }>({ status: 'initial' });
    const [errorData, setErrorData] = useState<any>();
    const stripe = useStripe();
    const elements = useElements();

    useEffect(() => {
        elements?.update({ amount: formAmount * 100 });
    }, [formAmount]);

    const onSubmit = async () => {
        try {
            if (!elements || !stripe) return;

            setErrorData(undefined);
            setPayment({ status: "processing" });

            const { error: submitError } = await elements.submit();

            if (submitError) {
                if (submitError.message) {
                    message.error(submitError.message);
                }

                return;
            }

            const { client_secret: clientSecret } = await createPaymentIntent(
                { amount, sessionId }
            );

            const { error: confirmError } = await stripe!.confirmPayment({
                elements,
                clientSecret,
                confirmParams: {
                    return_url: window.location.href,
                    payment_method_data: {
                        allow_redisplay: 'limited',
                        // billing_details: {
                        //     name: input.cardholderName,
                        // },
                    },
                },
            });

            if (confirmError) {
                setErrorData({
                    title: i18nText('errorPayment', locale),
                    message: confirmError.message ?? 'An unknown error occurred'
                });
            }
        } catch (err) {
            const { message } = err as StripeError;
            setErrorData({
                title: i18nText('errorPayment', locale),
                message: message ?? 'An unknown error occurred'
            });
        }
    };

    return (
        <WithError errorData={errorData}>
            <Form form={form} onFinish={onSubmit} style={{ display: 'flex', overflow: 'hidden', flexDirection: 'column', gap: 16, justifyContent: 'space-between', alignItems: 'center' }}>
                <div style={{ width: '100%' }}>
                    <PaymentElement
                        onChange={(e) => {
                            setPaymentType(e.value.type);
                        }}
                    />
                </div>
                <div>
                    <PaymentStatus status={payment.status}/>
                </div>
                <Button
                    className="btn-apply"
                    htmlType="submit"
                    disabled={
                        !["initial", "succeeded", "error"].includes(payment.status) ||
                        !stripe
                    }
                >
                    {`${i18nText('pay', locale)} ${amount}€`}
                </Button>
            </Form>
        </WithError>
    );
}

export const StripeElementsForm: FC<PaymentFormProps> = ({ amount, sessionId, locale }) => {
    return (
        <Elements
            stripe={getStripe()}
            options={{
                fonts: [{
                    cssSrc: 'https://fonts.googleapis.com/css2?family=Comfortaa&display=swap',
                }],
                appearance: {
                    variables: {
                        colorIcon: '#2c7873',
                        fontSizeBase: '16px',
                        colorPrimary: '#66A5AD',
                        colorBackground: '#F8F8F7',
                        colorText: '#000',
                        colorDanger: '#ff4d4f',
                        focusBoxShadow: 'none',
                        borderRadius: '8px'
                    },
                },
                currency: 'eur',
                mode: "payment",
                amount: amount*100,
            }}
        >
            <CheckoutForm amount={amount} sessionId={sessionId} locale={locale} />
        </Elements>
    );
};
