import Layout from '@/components/layouts';
import usePagination from '@/hooks/usePagination';
import {
    getMemberPenalties,
    submitDonation,
    submitBulkDonation,
    uploadDonationMedia,
    MemberPenalty,
} from '@/services/donation';
import { AxiosErrorResponse, BasePageProps, MediaFormValue } from '@/types';
import { authentication } from '@/utils/authentication';
import localeLinkGenerator from '@/utils/localeLinkGenerator';
import { errorMessageFormatter, mediaUrlGenerator } from '@/utils';
import { currencyFormatter } from '@/utils/currencyFormatter';
import { dateTimeTransformer } from '@/utils/timeTransformer';
import { useMutation, useQuery } from '@tanstack/react-query';
import { Button, Card, Checkbox, Modal, Tag, Upload, Empty } from 'antd';
import { UploadOutlined, DollarOutlined } from '@ant-design/icons';
import { GetServerSideProps, NextPage } from 'next';
import { useTranslation } from 'next-i18next';
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
import Link from 'next/link';
import { useState } from 'react';
import { toast } from 'react-toastify';

const DonationPage: NextPage<BasePageProps> = ({ member }) => {
    const { t } = useTranslation(['common', 'messages', 'layout']);
    const [pagination, setPagination] = usePagination<MemberPenalty>();

    const [selectedPenalties, setSelectedPenalties] = useState<string[]>([]);
    const [bulkModalOpen, setBulkModalOpen] = useState(false);
    const [singleModalOpen, setSingleModalOpen] = useState(false);
    const [activePenalty, setActivePenalty] = useState<MemberPenalty | null>(null);
    const [uploadedFiles, setUploadedFiles] = useState<MediaFormValue[]>([]);

    // Fetch penalties
    const { isFetching, data: penalties, refetch } = useQuery({
        queryKey: ['member-penalties', pagination],
        queryFn: async () => {
            const query = {
                page: pagination.page,
                pageSize: pagination.pageSize,
                sortField: pagination.sortField,
                sortOrder: pagination.sortOrder,
            };

            const response = await getMemberPenalties(query);

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

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

    // Mutations
    const submitMutation = useMutation({
        mutationFn: async (data: { penaltyId: string; amount: number; media: { mediaId: string }[] }) => {
            const response = await submitDonation(data);
            return response.data;
        },
        onSuccess() {
            refetch();
            setSingleModalOpen(false);
            setActivePenalty(null);
            setUploadedFiles([]);
        },
    });

    const submitBulkMutation = useMutation({
        mutationFn: async (data: { penaltyIds: string[]; amount: number; media: { mediaId: string }[] }) => {
            const response = await submitBulkDonation(data);
            return response.data;
        },
        onSuccess() {
            refetch();
            setBulkModalOpen(false);
            setSelectedPenalties([]);
            setUploadedFiles([]);
        },
    });

    // Handlers
    const pendingPenalties = (penalties || []).filter((p) => p.status === 'PENDING');

    const togglePenalty = (id: string) => {
        setSelectedPenalties((prev) =>
            prev.includes(id) ? prev.filter((pid) => pid !== id) : [...prev, id],
        );
    };

    const selectAll = () => {
        if (selectedPenalties.length === pendingPenalties.length) {
            setSelectedPenalties([]);
        } else {
            setSelectedPenalties(pendingPenalties.map((p) => p.id));
        }
    };

    const selectedTotal = pendingPenalties
        .filter((p) => selectedPenalties.includes(p.id))
        .reduce((sum, p) => sum + p.amount, 0);

    const openSingleUpload = (penalty: MemberPenalty) => {
        setActivePenalty(penalty);
        setUploadedFiles([]);
        setSingleModalOpen(true);
    };

    const handleSingleSubmit = () => {
        if (!activePenalty || uploadedFiles.length === 0) {
            toast.error('Please upload at least one file');
            return;
        }
        toast.promise(
            submitMutation.mutateAsync({
                penaltyId: activePenalty.id,
                amount: activePenalty.amount,
                media: uploadedFiles.map((f) => ({ mediaId: f.uid })),
            }),
            {
                pending: 'Submitting donation...',
                success: 'Donation submitted successfully',
                error: {
                    render({ data }) {
                        return errorMessageFormatter(data as AxiosErrorResponse);
                    },
                },
            },
        );
    };

    const handleBulkSubmit = () => {
        if (uploadedFiles.length === 0) {
            toast.error('Please upload at least one file');
            return;
        }
        toast.promise(
            submitBulkMutation.mutateAsync({
                penaltyIds: selectedPenalties,
                amount: selectedTotal,
                media: uploadedFiles.map((f) => ({ mediaId: f.uid })),
            }),
            {
                pending: 'Submitting donations...',
                success: 'Donations submitted successfully',
                error: {
                    render({ data }) {
                        return errorMessageFormatter(data as AxiosErrorResponse);
                    },
                },
            },
        );
    };

    const getStatusTag = (status: string) => {
        switch (status) {
            case 'PAID':
                return <Tag color="green">Paid</Tag>;
            case 'WAIVED':
                return <Tag color="blue">Waived</Tag>;
            default:
                return <Tag color="gold">Pending</Tag>;
        }
    };

    const breadCrumbItems = [
        {
            label: 'Donation',
            path: '/donation',
        },
    ];

    return (
        <Layout
            member={member}
            breadCrumbItems={breadCrumbItems}
            seoConfig={{ title: 'Donation' }}
            activeMenu={['donation']}
            withBackground
        >
            <div>
                {/* Select All and Pay Selected bar */}
                {pendingPenalties.length > 0 && (
                    <div className="flex flex-wrap items-center justify-between mb-4 p-3 bg-white rounded-lg shadow-sm">
                        <Checkbox
                            checked={selectedPenalties.length === pendingPenalties.length && pendingPenalties.length > 0}
                            indeterminate={selectedPenalties.length > 0 && selectedPenalties.length < pendingPenalties.length}
                            onChange={selectAll}
                        >
                            Select All ({pendingPenalties.length})
                        </Checkbox>
                        {selectedPenalties.length > 0 && (
                            <Button
                                type="primary"
                                icon={<DollarOutlined />}
                                onClick={() => {
                                    setUploadedFiles([]);
                                    setBulkModalOpen(true);
                                }}
                            >
                                Pay Selected ({selectedPenalties.length}) - RM {currencyFormatter(selectedTotal)}
                            </Button>
                        )}
                    </div>
                )}

                {/* Penalty cards */}
                <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
                    {(penalties || []).map((penalty) => (
                        <Card
                            key={penalty.id}
                            className={`${selectedPenalties.includes(penalty.id) ? 'border-blue-400 border-2' : ''}`}
                        >
                            <div className="flex items-start justify-between">
                                <div className="flex items-start gap-3">
                                    {penalty.status === 'PENDING' && (
                                        <Checkbox
                                            checked={selectedPenalties.includes(penalty.id)}
                                            onChange={() => togglePenalty(penalty.id)}
                                        />
                                    )}
                                    <div>
                                        <div className="font-bold text-lg">
                                            RM {currencyFormatter(penalty.amount)}
                                        </div>
                                        <div className="text-gray-500 text-sm">
                                            {penalty.studyGroupTask?.studyGroup?.name}
                                        </div>
                                        <div className="text-gray-400 text-xs mt-1">
                                            Task: {dateTimeTransformer(penalty.studyGroupTask?.taskDate)}
                                        </div>
                                        <div className="text-gray-400 text-xs">
                                            Created: {dateTimeTransformer(penalty.createdAt)}
                                        </div>
                                    </div>
                                </div>
                                <div className="flex flex-col items-end gap-2">
                                    {getStatusTag(penalty.status)}
                                    {penalty.status === 'PENDING' && (
                                        <Button
                                            type="primary"
                                            size="small"
                                            icon={<UploadOutlined />}
                                            onClick={() => openSingleUpload(penalty)}
                                        >
                                            Upload Donation
                                        </Button>
                                    )}
                                </div>
                            </div>

                            {/* Show existing receipts */}
                            {penalty.donationReceipts.length > 0 && (
                                <div className="mt-3 pt-3 border-t">
                                    <div className="text-sm font-semibold mb-2">Receipts:</div>
                                    {penalty.donationReceipts.map((receipt) => (
                                        <div key={receipt.id} className="flex items-center justify-between text-sm mb-1">
                                            <span>
                                                RM {currencyFormatter(receipt.amount)} -{' '}
                                                {receipt.status === 'APPROVED' ? (
                                                    <Tag color="green" className="text-xs">Approved</Tag>
                                                ) : receipt.status === 'REJECTED' ? (
                                                    <Tag color="red" className="text-xs">Rejected</Tag>
                                                ) : (
                                                    <Tag color="gold" className="text-xs">Pending</Tag>
                                                )}
                                            </span>
                                            <span className="text-gray-400">{dateTimeTransformer(receipt.createdAt)}</span>
                                        </div>
                                    ))}
                                </div>
                            )}
                        </Card>
                    ))}
                </div>

                {(!penalties || penalties.length === 0) && !isFetching && (
                    <Empty description="No penalties found" />
                )}

                {/* Pagination */}
                {pagination.total > pagination.pageSize && (
                    <div className="flex justify-center mt-4">
                        <Button
                            disabled={pagination.page <= 1}
                            onClick={() => setPagination((prev) => ({ ...prev, page: prev.page - 1 }))}
                        >
                            Previous
                        </Button>
                        <span className="mx-4 flex items-center">
                            Page {pagination.page} of {Math.ceil(pagination.total / pagination.pageSize)}
                        </span>
                        <Button
                            disabled={pagination.page >= Math.ceil(pagination.total / pagination.pageSize)}
                            onClick={() => setPagination((prev) => ({ ...prev, page: prev.page + 1 }))}
                        >
                            Next
                        </Button>
                    </div>
                )}

                {/* Single Upload Modal */}
                <Modal
                    title={`Upload Donation Receipt - RM ${activePenalty ? currencyFormatter(activePenalty.amount) : '0.00'}`}
                    open={singleModalOpen}
                    onCancel={() => {
                        setSingleModalOpen(false);
                        setActivePenalty(null);
                        setUploadedFiles([]);
                    }}
                    footer={[
                        <Button key="cancel" onClick={() => setSingleModalOpen(false)}>
                            Cancel
                        </Button>,
                        <Button
                            key="submit"
                            type="primary"
                            loading={submitMutation.isLoading}
                            disabled={uploadedFiles.length === 0}
                            onClick={handleSingleSubmit}
                        >
                            Submit
                        </Button>,
                    ]}
                >
                    {activePenalty && (
                        <div className="mb-4">
                            <p><strong>Study Group:</strong> {activePenalty.studyGroupTask?.studyGroup?.name}</p>
                            <p><strong>Amount:</strong> RM {currencyFormatter(activePenalty.amount)}</p>
                        </div>
                    )}
                    <Upload
                        customRequest={(option) => uploadDonationMedia('/member/donation/upload', option)}
                        onChange={(info) => {
                            if (info.file.status === 'done') {
                                const response = info.file.response as MediaFormValue;
                                setUploadedFiles((prev) => [...prev, response]);
                            }
                        }}
                        onRemove={(file) => {
                            const response = file.response as MediaFormValue;
                            if (response) {
                                setUploadedFiles((prev) => prev.filter((f) => f.uid !== response.uid));
                            }
                        }}
                        listType="picture"
                        maxCount={5}
                    >
                        <Button icon={<UploadOutlined />}>Upload Receipt</Button>
                    </Upload>
                </Modal>

                {/* Bulk Upload Modal */}
                <Modal
                    title="Pay Selected Penalties"
                    open={bulkModalOpen}
                    onCancel={() => {
                        setBulkModalOpen(false);
                        setUploadedFiles([]);
                    }}
                    footer={[
                        <Button key="cancel" onClick={() => setBulkModalOpen(false)}>
                            Cancel
                        </Button>,
                        <Button
                            key="submit"
                            type="primary"
                            loading={submitBulkMutation.isLoading}
                            disabled={uploadedFiles.length === 0}
                            onClick={handleBulkSubmit}
                        >
                            Submit
                        </Button>,
                    ]}
                    width={600}
                >
                    <div className="mb-4">
                        <h4 className="font-semibold mb-2">Selected Penalties ({selectedPenalties.length}):</h4>
                        {pendingPenalties
                            .filter((p) => selectedPenalties.includes(p.id))
                            .map((p) => (
                                <div key={p.id} className="flex justify-between py-1 border-b">
                                    <span>{p.studyGroupTask?.studyGroup?.name}</span>
                                    <span>RM {currencyFormatter(p.amount)}</span>
                                </div>
                            ))}
                        <div className="flex justify-between py-2 font-bold text-lg">
                            <span>Total:</span>
                            <span>RM {currencyFormatter(selectedTotal)}</span>
                        </div>
                    </div>

                    <Upload
                        customRequest={(option) => uploadDonationMedia('/member/donation/upload', option)}
                        onChange={(info) => {
                            if (info.file.status === 'done') {
                                const response = info.file.response as MediaFormValue;
                                setUploadedFiles((prev) => [...prev, response]);
                            }
                        }}
                        onRemove={(file) => {
                            const response = file.response as MediaFormValue;
                            if (response) {
                                setUploadedFiles((prev) => prev.filter((f) => f.uid !== response.uid));
                            }
                        }}
                        listType="picture"
                        maxCount={5}
                    >
                        <Button icon={<UploadOutlined />}>Upload Receipt</Button>
                    </Upload>
                </Modal>
            </div>
        </Layout>
    );
};

export default DonationPage;

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

        return {
            props: {
                member: authResponse,
                ...(await serverSideTranslations(locale as string, ['layout', 'common', 'messages', 'api-messages'])),
            },
        };
    } 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,
            },
        };
    }
};
