import { FILE_SIZE_LIMIT } from '@/configs';
import { BookTokenSubscriptionStatus, UploadProofOfPaymentPayload } from '@/types/book-token';
import { errorMessageFormatter, normFile } from '@/utils';
import { UploadOutlined } from '@ant-design/icons';
import { Button, DatePicker, Form, Modal, Upload } from 'antd';
import { Dispatch, SetStateAction, useState } from 'react';
import { useTranslation } from 'next-i18next';
import { toast } from 'react-toastify';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { bookTokenKeys, getBookTokenSubscriptionById, uploadProofMedia, uploadProofOfPayment } from '@/services/book-token';
import { AxiosErrorResponse } from '@/types';
import { mediaFormValueToResponse, mediaResponseToFormValue } from '@/transformer/media/media';
import dayjs from 'dayjs';

interface UploadProofOfPaymentProps {
    open: boolean;
    setOpen: Dispatch<SetStateAction<boolean>>;
    selectedBookTokenId: string | null;
}

const UploadProofOfPayment: React.FC<UploadProofOfPaymentProps> = ({ open, setOpen, selectedBookTokenId }) => {
    const { t } = useTranslation(['book-token', 'common', 'messages', 'layout']);
    const [uploadProofOfPaymentForm] = Form.useForm();
    const queryClient = useQueryClient();
    const [rejected, setRejected] = useState(false);

    const { data, isFetching } = useQuery({
        queryKey: bookTokenKeys.id(selectedBookTokenId as string),
        queryFn: async () => {
            const response = await getBookTokenSubscriptionById(selectedBookTokenId as string);

            return response.data;
        },
        enabled: !!selectedBookTokenId && open,
        onSuccess(data) {
            const { expiredAt, paymentStatus, ...rest } = data;

            const isRejected = paymentStatus === BookTokenSubscriptionStatus.REJECTED;
            setRejected(isRejected);

            uploadProofOfPaymentForm.setFieldsValue({
                ...rest,
                paymentStatus: paymentStatus,
                package: data.package.name,
                expiredAt: expiredAt ? dayjs.tz(expiredAt) : undefined,
                uploadFile: data.bookTokenSubscriptionMedias.map(mediaResponseToFormValue),
            });
        },
    });

    const uploadProofOfPaymentMutation = useMutation({
        mutationFn: async (data: UploadProofOfPaymentPayload) => {
            const response = await uploadProofOfPayment(selectedBookTokenId as string, data);

            return response;
        },
        onSuccess: () => {
            queryClient.invalidateQueries(bookTokenKeys.pagination());
            onCancelHandler();
        },
    });

    const onCancelHandler = () => {
        uploadProofOfPaymentForm.resetFields();
        setOpen(false);
    };

    const onUploadProofOfPaymentHandler = () => {
        uploadProofOfPaymentForm.validateFields().then(async (values) => {
            const formattedData = values.uploadFile.map(mediaFormValueToResponse);
            const body: UploadProofOfPaymentPayload = {
                medias: formattedData,
                paymentDate: values.paymentDate,
            };

            toast.promise(uploadProofOfPaymentMutation.mutateAsync(body), {
                pending: t('messages:uploading-proof-of-payment'),
                success: t('messages:proof-of-payment-uploaded'),
                error: {
                    render({ data }) {
                        return t(errorMessageFormatter(data as AxiosErrorResponse));
                    },
                },
            });
        });
    };

    return (
        <Modal open={open} onCancel={onCancelHandler} footer={null}>
            <Form form={uploadProofOfPaymentForm} layout="vertical">
                <Form.Item name="paymentDate" label={t('payment-date')} rules={[{ required: true, message: t('messages:required') }]}>
                    <DatePicker className="w-full" size="large" />
                </Form.Item>
                <Form.Item
                    name="uploadFile"
                    label={t('upload-file')}
                    rules={[{ required: true, message: t('messages:required') }]}
                    getValueFromEvent={normFile}
                    valuePropName="fileList"
                >
                    <Upload
                        multiple
                        className="!w-full"
                        maxCount={3}
                        beforeUpload={(file) => {
                            const isLTSizeLimit = file.size / 1024 / 1024 > FILE_SIZE_LIMIT;

                            if (isLTSizeLimit) {
                                toast.error(t('messages:file-too-large', { fileName: file.name, size: FILE_SIZE_LIMIT }));
                                return Upload.LIST_IGNORE;
                            }

                            return true;
                        }}
                        customRequest={(options) => uploadProofMedia('/member/book-token/upload', options)}
                    >
                        <Button block icon={<UploadOutlined />} size="large">
                            {t('common:upload-receipt')}
                        </Button>
                    </Upload>
                </Form.Item>
            </Form>
            <div className="flex flex-col md:flex-row gap-4">
                <Button block onClick={onCancelHandler} loading={uploadProofOfPaymentMutation.isLoading}>
                    {t('common:cancel')}
                </Button>
                <Button block type="primary" onClick={onUploadProofOfPaymentHandler} loading={uploadProofOfPaymentMutation.isLoading}>
                    {t('common:submit')}
                </Button>
            </div>
        </Modal>
    );
};

export default UploadProofOfPayment;
