import HtmlParser from '@/components/HtmlParser';
import BookTokenStatusTag from '@/components/book-token/BookTokenStatusTag';
import RequestBookToken from '@/components/book-token/modals/RequestBookToken';
import UploadProofOfPayment from '@/components/book-token/modals/UploadProofOfPayment';
import ViewPayment from '@/components/book-token/modals/ViewPayment';
import Layout from '@/components/layouts';
import ConfirmationModal from '@/components/modals/ConfirmationModal';
import ActionDropdown from '@/components/ui/ActionDropdown';
import usePagination from '@/hooks/usePagination';
import { bookTokenKeys, cancelRequestBookToken, getBookTokenSubscriptionList } from '@/services/book-token';
import { getSupport } from '@/services/company-info';
import { AxiosErrorResponse, BasePageProps } from '@/types';
import { BookTokenSubscriptionList, BookTokenSubscriptionStatus } from '@/types/book-token';
import { authentication, errorMessageFormatter, localeLinkGenerator } from '@/utils';
import conditionalReturn from '@/utils/conditionalReturn';
import { currencyFormatter } from '@/utils/currencyFormatter';
import { dateTimeTransformer } from '@/utils/timeTransformer';
import { DownloadOutlined, EyeOutlined, PlusCircleOutlined } from '@ant-design/icons';
import { useMutation, useQuery } from '@tanstack/react-query';
import { Alert, Button, MenuProps, Skeleton, Table, Tag, Tooltip } from 'antd';
import { ColumnsType } from 'antd/es/table';
import { GetServerSideProps, NextPage } from 'next';
import { Trans, useTranslation } from 'next-i18next';
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
import Link from 'next/link';
import { useState } from 'react';
import { AiOutlineExclamationCircle } from 'react-icons/ai';
import { toast } from 'react-toastify';

const Index: NextPage<BasePageProps> = ({ member }) => {
    const { t } = useTranslation(['book-token', 'common', 'messages', 'layout']);
    const [pagination, setPagination, paginationOnChange] = usePagination<BookTokenSubscriptionList>();

    const [isRequestBookTokenModalOpen, setIsRequestBookTokenModalOpen] = useState<boolean>(false);
    const [isUploadProofOfPaymentModalOpen, setIsUploadProofOfPaymentModalOpen] = useState<boolean>(false);
    const [isViewPaymentProofModalOpen, setIsViewPaymentProofModalOpen] = useState<boolean>(false);
    const [selectedBookTokenId, setSelectedBookTokenId] = useState<string | null>(null);
    const [selectedBookToken, setSelectedBookToken] = useState<BookTokenSubscriptionList | null>(null);

    const { isFetching, data, refetch } = useQuery({
        queryKey: bookTokenKeys.pagination(pagination),
        queryFn: async () => {
            const query = {
                page: pagination.page,
                pageSize: pagination.pageSize,
                sortField: pagination.sortField,
                sortOrder: pagination.sortOrder,
            };

            const response = await getBookTokenSubscriptionList(query);

            setPagination((prev) => {
                return {
                    ...prev,
                    page: response.data.page,
                    total: response.data.total,
                };
            });

            return response.data.rows;
        },
    });

    const { isFetching: isBankDetailFetching, data: bankDetails } = useQuery({
        queryKey: ['companyInformation'],
        queryFn: async () => {
            const response = await getSupport();
            return response.data;
        },
    });

    const cancelRequestMutation = useMutation({
        mutationFn: async (bookTokenId: string) => {
            const response = await cancelRequestBookToken(bookTokenId);
            return response.data;
        },
        onSuccess: () => {
            refetch();
        },
    });

    const onCancelRequestHandler = (bookTokenId: string) => {
        toast.promise(cancelRequestMutation.mutateAsync(bookTokenId), {
            pending: t('messages:cancelling-book-token-request'),
            success: t('messages:book-token-request-cancelled'),
            error: {
                render({ data }) {
                    return t(errorMessageFormatter(data as AxiosErrorResponse));
                },
            },
        });
    };

    const columns: ColumnsType<BookTokenSubscriptionList> = [
        {
            title: t('ref-no'),
            dataIndex: 'displayId',
            key: 'displayId',
            width: 160,
        },
        {
            title: t('package'),
            dataIndex: ['package', 'name'],
            key: 'package',
            width: 130,
        },
        {
            title: t('package-description'),
            dataIndex: ['package', 'description'],
            key: 'package-description',
            width: 200,
            render: (description: string) => {
                return <HtmlParser html={description} />;
            },
        },
        {
            title: t('quantity'),
            dataIndex: 'quantity',
            key: 'quantity',
            width: 130,
        },
        {
            title: t('number-of-book-tokens'),
            dataIndex: 'numberOfBookTokens',
            key: 'numberOfBookTokens',
            width: 130,
        },
        {
            title: t('unit-price'),
            dataIndex: ['package', 'price'],
            key: 'price',
            width: 200,
            render: (price: number) => {
                return `MYR ${currencyFormatter(price)}`;
            },
        },
        {
            title: t('common:total-amount'),
            dataIndex: ['package', 'price'],
            key: 'totalAmount',
            width: 220,
            render: (price: number, bookToken) => {
                return `MYR ${currencyFormatter(price * bookToken.quantity)}`;
            },
        },
        {
            title: t('payment-status'),
            dataIndex: 'paymentStatus',
            key: 'paymentStatus',
            width: 160,
            render: (paymentStatus: BookTokenSubscriptionStatus, bookToken) => {
                return (
                    <div className="flex items-center">
                        <BookTokenStatusTag status={paymentStatus} />
                        {paymentStatus === 'REJECTED' && (
                            <Tooltip
                                title={
                                    <div className="flex flex-col gap-1 p-2">
                                        <span className="font-bold">{t('reason-for-rejection')}</span>
                                        <span>{bookToken?.reason}</span>
                                    </div>
                                }
                            >
                                <AiOutlineExclamationCircle className="text-sm md:text-md" />
                            </Tooltip>
                        )}
                    </div>
                );
            },
        },
        {
            title: t('common:created-at'),
            dataIndex: 'createdAt',
            key: 'createdAt',
            render: (createdAt: string) => {
                return dateTimeTransformer(createdAt);
            },
        },
        {
            title: t('invoice'),
            dataIndex: 'id',
            key: 'invoice',
            width: 80,
            render: (bookTokenSubscriptionId: string) => {
                return (
                    <Link href={`/bill/invoice/${bookTokenSubscriptionId}`} target="_blank" className="flex justify-center">
                        <EyeOutlined className="text-base" />
                    </Link>
                );
            },
        },
        {
            title: t('receipt'),
            dataIndex: 'id',
            key: 'receipt',
            width: 80,
            render: (bookTokenSubscriptionId: string, bookToken) => {
                return (
                    <div className="flex justify-center">
                        {bookToken.paymentStatus === BookTokenSubscriptionStatus.PAID ? (
                            <Link href={`/bill/receipt/${bookTokenSubscriptionId}`} target="_blank" className="flex justify-center">
                                <EyeOutlined className="text-base" />
                            </Link>
                        ) : (
                            '-'
                        )}
                    </div>
                );
            },
        },
        {
            title: t('common:actions'),
            dataIndex: 'createdAt',
            key: 'action',
            width: 120,
            render: (_: unknown, record) => {
                const items: MenuProps['items'] = [
                    ...conditionalReturn(record.paymentStatus !== BookTokenSubscriptionStatus.PAID, [
                        {
                            label: t('common:upload-proof-of-payment'),
                            key: 'uploadProofOfPayment',
                            onClick: () => {
                                setSelectedBookTokenId(record.id);
                                setIsUploadProofOfPaymentModalOpen(true);
                            },
                            className: 'text-center',
                        },
                    ]),
                    ...conditionalReturn(record.paymentStatus === BookTokenSubscriptionStatus.PAID, [
                        {
                            label: t('common:view'),
                            key: 'view',
                            onClick: () => {
                                setSelectedBookToken(record);
                                setIsViewPaymentProofModalOpen(true);
                            },
                            className: 'text-center',
                        },
                    ]),
                    ...conditionalReturn(record.paymentStatus === BookTokenSubscriptionStatus.UNPAID, [
                        {
                            label: (
                                <ConfirmationModal
                                    title={t('book-token-cancel-confirmation')}
                                    message={
                                        <Trans
                                            i18nKey={'messages:are-you-sure-you-want-to-cancel-request-of-this-book-token?'}
                                            components={{
                                                strong: <strong />,
                                            }}
                                            values={{
                                                name: member.fullName,
                                            }}
                                        />
                                    }
                                    okText={t('cancel-request')}
                                    cancelText={t('not-to-cancel')}
                                    okButtonProps={{ danger: true }}
                                    onOk={() => {
                                        onCancelRequestHandler(record.id);
                                    }}
                                    reason={false}
                                    width={400}
                                >
                                    <Button
                                        type="link"
                                        ghost
                                        block
                                        className="!p-0 hover:!text-white text-black"
                                        style={{ transition: 'none' }}
                                        loading={cancelRequestMutation.isLoading}
                                    >
                                        {t('cancel-request')}
                                    </Button>
                                </ConfirmationModal>
                            ),
                            key: 'cancel',
                            danger: true,
                            className: 'text-center !p-0',
                        },
                    ]),
                ];

                if (items.length === 0) {
                    return '-';
                }

                return <ActionDropdown items={items} />;
            },
        },
    ];

    const breadCrumbItems = [
        {
            label: t('layout:book-token'),
            path: '/book-token',
        },
    ];

    return (
        <Layout
            member={member}
            breadCrumbItems={breadCrumbItems}
            seoConfig={{
                title: t('book-token'),
            }}
            withBackground
            activeMenu={['book-token']}
        >
            {isFetching || isBankDetailFetching ? (
                <Skeleton active />
            ) : (
                <>
                    <div className="flex flex-col lg:flex-row gap-4 mb-4">
                        <Alert
                            message={t('request-book-token')}
                            description={
                                <div>
                                    <div>{t('click-on-the-request-book-token-button')}</div>
                                    <div>{t('select-package-and-enter-quantity-you-want')}</div>
                                    <div>{t('upload-proof-of-payment-and-wait-for-admin-to-approve')}</div>
                                    <div>{t('while-waiting-for-admin-to-approve-please-proceed-to-order-book')}</div>
                                    <div>{t('once-admin-approve-please-proceed-to-request-join-study-group')}</div>
                                </div>
                            }
                            type="info"
                            showIcon
                            style={{ backgroundColor: '#f0f5ff', border: '1px solid #adc6ff', borderRadius: '5px' }}
                            className="w-full basis-2/3"
                        />
                        <Alert
                            message={`${t('please-make-payment-to')}:`}
                            description={
                                <div>
                                    <div>
                                        {t('bank-name')}: {bankDetails?.bankName}
                                    </div>
                                    <div>
                                        {t('account-holder')}: {bankDetails?.accountHolderName}
                                    </div>
                                    <div>
                                        {t('account-number')}: {bankDetails?.accountNumber}
                                    </div>
                                </div>
                            }
                            type="info"
                            showIcon
                            style={{ backgroundColor: '#f0f5ff', border: '1px solid #adc6ff', borderRadius: '5px' }}
                            className="w-full basis-1/3"
                        />
                    </div>
                    <div className="flex flex-col sm:flex-row justify-start mb-4 gap-4 sm:justify-between">
                        <div>
                            <Tag className="text-md p-[5px] items-center flex w-fit" color="cyan">
                                {t('balance-token(s)') + ': ' + member?.bookTokens}
                            </Tag>
                        </div>
                        <div className="flex gap-4 flex-col sm:flex-row">
                            <Button type="primary" ghost icon={<DownloadOutlined />} href="/bill/quotation" target="_blank">
                                {t('generate-quotation')}
                            </Button>
                            <Button type="primary" icon={<PlusCircleOutlined />} onClick={() => setIsRequestBookTokenModalOpen(true)}>
                                {t('request-book-token')}
                            </Button>
                        </div>
                    </div>
                    <Table
                        columns={columns}
                        dataSource={data}
                        loading={isFetching}
                        rowKey={(record) => record.id}
                        scroll={{ x: 1000 }}
                        onChange={paginationOnChange}
                        pagination={{
                            current: pagination.page,
                            pageSize: pagination.pageSize,
                            defaultPageSize: 1,
                            showSizeChanger: true,
                            pageSizeOptions: [10, 25, 50, 100],
                            showTotal: (total, range) => t('common:pagination', { range0: range[0], range1: range[1], total: total }),
                            total: pagination.total,
                        }}
                    />
                    <RequestBookToken open={isRequestBookTokenModalOpen} setOpen={setIsRequestBookTokenModalOpen} />
                    <UploadProofOfPayment
                        selectedBookTokenId={selectedBookTokenId}
                        open={isUploadProofOfPaymentModalOpen}
                        setOpen={setIsUploadProofOfPaymentModalOpen}
                    />
                    <ViewPayment selectedBookToken={selectedBookToken} open={isViewPaymentProofModalOpen} setOpen={setIsViewPaymentProofModalOpen} />
                </>
            )}
        </Layout>
    );
};

export default Index;

export const getServerSideProps: GetServerSideProps = async ({ locale, req, resolvedUrl }) => {
    try {
        const authResponse = await authentication(req);

        return {
            props: {
                member: authResponse,
                ...(await serverSideTranslations(locale as string, [
                    'book-token',
                    'layout',
                    'common',
                    'messages',
                    'auth',
                    'api-messages',
                    'my-profile',
                ])),
            },
        };
    } catch (error: any) {
        if (error.response?.data?.unauthorized) {
            return {
                redirect: {
                    destination: localeLinkGenerator(locale, `/unauthorized`),
                    permanent: false,
                },
            };
        }

        return {
            redirect: {
                destination: localeLinkGenerator(locale, `/?redirect=/${resolvedUrl}`),
                permanent: false,
            },
        };
    }
};
