import { FILE_SIZE_LIMIT } from '@/configs';
import { getBookOrderById, updateBookOrderById, uploadBookOrderMedia } from '@/services/book-order';
import { mediaFormValueToResponse, mediaResponseToFormValue } from '@/transformer/media/media';
import { AxiosErrorResponse, MediaFormValue } from '@/types';
import { BookOrderStatus, UpdateBookOrderDetails } from '@/types/book-order';
import { errorMessageFormatter, normFile } from '@/utils';
import { UploadOutlined } from '@ant-design/icons';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { Button, Empty, Form, Input, InputNumber, Modal, Select, Skeleton, Upload } from 'antd';
import { useTranslation } from 'next-i18next';
import { Dispatch, SetStateAction } from 'react';
import { toast } from 'react-toastify';

interface ViewBookOrderDetailsProps {
    open: boolean;
    setOpen: Dispatch<SetStateAction<boolean>>;
    selectedBookOrderId: string | null;
}

const ViewBookOrderDetails: React.FC<ViewBookOrderDetailsProps> = ({ open, setOpen, selectedBookOrderId }) => {
    const { t } = useTranslation(['book-order', 'common', 'messages']);
    const [bookOrderForm] = Form.useForm();
    const queryClient = useQueryClient();

    const { data, isFetching } = useQuery({
        queryKey: ['book-order', selectedBookOrderId],
        queryFn: async () => {
            const response = await getBookOrderById(selectedBookOrderId as string);

            return response.data;
        },
        enabled: !!selectedBookOrderId && open,
        onSuccess(data) {
            const { member, book, ...rest } = data;

            bookOrderForm.setFieldsValue({
                memberName: member.fullName,
                bookName: book.name,
                ...rest,
                uploadFile: (data.media ?? []).map(mediaResponseToFormValue),
            });
        },
    });

    /* Update Mutation */
    const updateBookOrderMutation = useMutation({
        mutationFn: async (body: UpdateBookOrderDetails) => {
            const response = await updateBookOrderById(selectedBookOrderId as string, body);
            return response.data;
        },
        onSuccess: () => {
            queryClient.invalidateQueries(['book-order']);
            setOpen(false);
        },
    });

    const onCancelHandler = () => {
        setOpen(false);
    };

    const onUpdateHandler = async () => {
        bookOrderForm.validateFields().then(async (values) => {
            const formattedData = values.uploadFile.map(mediaFormValueToResponse);
            const { memberName, bookName, uploadFile, ...rest } = values;
            const body: UpdateBookOrderDetails = {
                ...rest,
                media: formattedData as unknown as MediaFormValue[],
            };

            toast.promise(updateBookOrderMutation.mutateAsync(body), {
                pending: t('messages:updating-book-order'),
                success: t('messages:book-order-updated'),
                error: {
                    render({ data }) {
                        return t(errorMessageFormatter(data as AxiosErrorResponse));
                    },
                },
            });
        });
    };

    return (
        <Modal footer={null} open={open} onCancel={onCancelHandler} title={data?.displayId}>
            {isFetching ? (
                <Skeleton />
            ) : !data ? (
                <Empty />
            ) : (
                <>
                    <Form form={bookOrderForm} layout="vertical">
                        <Form.Item name="memberName" label={t('member-name')}>
                            <Input disabled size="large" />
                        </Form.Item>
                        <Form.Item name="bookName" label={t('book-name')}>
                            <Input disabled size="large" />
                        </Form.Item>
                        <Form.Item name="quantity" label={t('book-quantity')} rules={[{ required: true, message: t('messages:required') }]}>
                            <InputNumber min={1} className="w-full" size="large" />
                        </Form.Item>
                        <Form.Item name="bookPrice" label={t('book-price')} rules={[{ required: true, message: t('messages:required') }]}>
                            <InputNumber min={1} className="w-full" size="large" />
                        </Form.Item>
                        <Form.Item name="status" label={t('payment-status')} rules={[{ required: true, message: t('messages:required') }]}>
                            <Select
                                size="large"
                                options={[
                                    { label: t('pending'), value: BookOrderStatus.PENDING },
                                    { label: t('unpaid'), value: BookOrderStatus.UNPAID },
                                    { label: t('paid'), value: BookOrderStatus.PAID },
                                ]}
                                disabled
                            />
                        </Form.Item>
                        <Form.Item
                            name="uploadFile"
                            label={t('payment-slip')}
                            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) => uploadBookOrderMedia('/staff/book-order/upload', options)}
                            >
                                <Button block icon={<UploadOutlined />} size="large">
                                    {t('common:upload-payment-slip')}
                                </Button>
                            </Upload>
                        </Form.Item>
                    </Form>
                    <div className="flex flex-col lg:flex-row gap-4">
                        <Button block onClick={onCancelHandler} loading={updateBookOrderMutation.isLoading}>
                            {t('common:cancel')}
                        </Button>
                        <Button block type="primary" onClick={onUpdateHandler} loading={updateBookOrderMutation.isLoading}>
                            {t('common:update')}
                        </Button>
                    </div>
                </>
            )}
        </Modal>
    );
};

export default ViewBookOrderDetails;
