'use client';
import ActionPopMenu from '@/components/common/ActionPopMenu';
import { type ColumnData, MyTable } from '@/components/common/MyTable';
import BaseButton from '@/components/ui-kit/BaseButton';
import BaseInput from '@/components/ui-kit/BaseInput';
import { selectDefaultStyles } from '@/components/ui-kit/BaseReactSelect';
import { useAuthContext } from '@/context/auth-context';
import type { BoxStatus, IBox, PrintStatus } from '@/data/box/box.model';
import { box_requests } from '@/data/box/box.requests';
import type { Product, UpdateProductBodyType } from '@/data/item/item.mode';
import { item_requests } from '@/data/item/item.requests';
import { party_requests } from '@/data/party/party.requests';
import { DEFAULT_PAGE_SIZE, pageLinks } from '@/helpers/constants';
import useInput from '@/hooks/useInput';
import { useMyNavigation } from '@/hooks/useMyNavigation';
import { useMyTranslation } from '@/hooks/useMyTranslation';
import useRequest from '@/hooks/useRequest';
import { useModalStore } from '@/modalStorage/modalSlice';
import { useBoxIdStore } from '@/modalStorage/partyId';
import { notifyUnknownError } from '@/services/notification';
import { CheckCircle, FilterListOff, Print, RemoveRedEye, Search } from '@mui/icons-material';
import { Box, Button, CircularProgress, FormControl, MenuItem, Select, Stack, Typography } from '@mui/material';
import { CloseIcon } from 'next/dist/client/components/react-dev-overlay/internal/icons/CloseIcon';
import { useRouter, useSearchParams } from 'next/navigation';
import type React from 'react';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useForm } from 'react-hook-form';
import AsyncSelect from 'react-select/async';
import { useReactToPrint } from 'react-to-print';
import BoxesPrintList from '../boxes-print/BoxesPrintList';
import CustomModal from '../customModal/CustomModal';

type Props = {};

const style = {
    position: 'absolute',
    top: '50%',
    left: '50%',
    transform: 'translate(-50%, -50%)',
    width: 400,
    bgcolor: 'background.paper',
    border: '2px solid #000',
    boxShadow: 24,
    display: 'flex',
    flexDirection: 'column',
    gap: '10px',
    p: 4,
};

const DashboardAcceptancePage = () => {
    // Redux for modal state
    const { isOpen: isModalOpen, openModal, closeModal } = useModalStore();
    const t = useMyTranslation();
    const navigation = useMyNavigation();
    const { isAdmin } = useAuthContext();
    const router = useRouter();

    // State management
    const [page, setPage] = useState(1);
    const [pageSize] = useState(DEFAULT_PAGE_SIZE);
    const { value: keyword, onChange: handleKeyword, setValue: setKeyword } = useInput('');
    const [boxStatusFilter, setBoxStatusFilter] = useState<BoxStatus | undefined>(undefined);
    const [trackId, setTrackId] = useState<string>();
    const [partyFilter, setPartyFilter] = useState<{ label: string; value: number } | undefined>(undefined);
    const [boxFilter, setBoxFilter] = useState<{ label: string; value: number } | undefined>(undefined);
    const [deleteIds, setDeleteIds] = useState<number[]>([]);
    const [downloadIds, setDownloadIds] = useState<number[]>([]);
    const [changeStatusIds, setChangeStatusIds] = useState<number[]>([]);
    const [boxAmounts, setBoxAmounts] = useState<Record<number, { totalAmount: number; totalAccepted: number }>>({});
    const [printStatuses, setPrintStatuses] = useState<Record<number, string>>({});
    const [hasMore, setHasMore] = useState(true);
    const [isFetching, setIsFetching] = useState(false);
    const [allData, setAllData] = useState<IBox[]>([]);
    const searchParams = useSearchParams();
    const boxId = searchParams.get('boxId');
    const { boxesIdAccepted, setBoxIdAccepted } = useBoxIdStore();

    // Print related state
    const [selectedBoxForPrint, setSelectedBoxForPrint] = useState<IBox | null>(null);
    const [selectedBoxDetails, setSelectedBoxDetails] = useState<any>(null);
    const printRef = useRef<HTMLDivElement>(null);
    const tableContainerRef = useRef<HTMLDivElement>(null);

    // Print functionality
    const handlePrint = useReactToPrint({
        contentRef: printRef,
        onAfterPrint: () => {
            setSelectedBoxForPrint(null);
            setSelectedBoxDetails(null);
        },
    });

    // Fetch party options
    const { data: defaultPartyOptions } = useRequest(() => party_requests.getAll({}), {
        enabled: true,
        selectData(data) {
            return data.data.data.data.map(p => ({ value: p.id, label: p.name }));
        },
        placeholderData: [],
    });

    const partyOptions = (inputValue: string) => {
        return party_requests.getAll({ partyName: inputValue }).then(res => {
            return res.data.data.data.map(p => ({ label: p.name, value: p.id }));
        });
    };

    // Print box handler
    const onPrintBox = async (boxData: IBox) => {
        try {
            const response = await box_requests.find({ packetId: boxData.id });
            const boxOne = response.data.data;
            const detailedBoxData = {
                id: +boxData.id,
                box_name: boxOne.packet.name,
                net_weight: +boxOne.packet.brutto,
                box_weight: +boxOne.packet.boxWeight,
                box_type: boxOne.packet.boxType,
                box_size: boxOne.packet.volume,
                passportName: boxOne.packet.passportName,
                status: boxOne.packet.status,
                packetId: boxData.id,
                partyId: +boxOne.packet.partyId,
                partyName: boxOne.packet.partyName,
                passportId: boxOne.client?.passportId,
                client_id: boxOne.packet?.cargoId,
                clientName: boxOne.client?.passportName,
                products_list: boxOne.items.map((item: any) => ({
                    id: item.id,
                    price: item.price,
                    cargoId: item.cargoId,
                    trekId: item.trekId,
                    name: item.name,
                    nameRu: item.nameRu,
                    amount: +item.amount,
                    acceptedNumber: item.acceptedNumber,
                    weight: +item.weight,
                })),
            };
            setSelectedBoxDetails(detailedBoxData);
            setTimeout(() => {
                handlePrint();
            }, 100);
        } catch (error) {}
    };

    // Memoized options
    const boxStatusOptions = useMemo(() => {
        const p = ['READY_TO_INVOICE'] as BoxStatus[];
        if (isAdmin) {
            p.push('READY');
        }
        return p;
    }, [isAdmin]);

    const printOptions = useMemo(() => {
        const p = ['false'] as PrintStatus[];
        if (isAdmin) {
            p.push('false');
        }
        return p;
    }, [isAdmin]);

    // Main data fetching query with optimized refresh handling
    const getBoxesQuery = useRequest(
        () =>
            box_requests.getAll({
                page: page,
                cargoId: keyword,
                partyId: partyFilter?.value,
                status: boxStatusFilter,
                direction: 'desc',
                sort: 'id',
            }),
        {
            dependencies: [page, boxStatusFilter, keyword, partyFilter],
            selectData(data) {
                return data.data.data;
            },
            onSuccess: data => {
                // Only update data if the page or filters have changed
                if (page === 1) {
                    setAllData(data.data.data.data);
                } else {
                    // Prevent duplicate data
                    setAllData(prev => {
                        const existingIds = new Set(prev.map(box => box.id));
                        const newData = data.data.data.data.filter(box => !existingIds.has(box.id));
                        return [...prev, ...newData];
                    });
                }
                setHasMore(data.data.data.data.length === pageSize);
                setIsFetching(false);
            },
        }
    );

    // Secondary list query
    const getListQuery = useRequest(
        () =>
            item_requests.getAll({
                page: page,
                trekId: trackId,
                packetId: boxFilter?.value,
                partyId: partyFilter?.value,
            }),
        {
            dependencies: [page, trackId, boxFilter?.value, partyFilter?.value],
            selectData(data) {
                return data.data.data;
            },
        }
    );

    // Form state for item amounts
    const [values, setValues] = useState<{ [trackId: string]: number | '' }>({});

    const handleAmountChange = (event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>, max: number, trackId: string) => {
        const val = Number(event.target.value);
        if (val >= 1 && val <= max) {
            setValues(prev => ({ ...prev, [trackId]: val }));
        } else if (event.target.value === '') {
            setValues(prev => ({ ...prev, [trackId]: '' }));
        }
    };

    const loading = getBoxesQuery.loading;

    // Page change handler
    const handleChange = useCallback(
        (newPage: number) => {
            if (!isFetching && hasMore) {
                setIsFetching(true);
                setPage(newPage);
            }
        },
        [isFetching, hasMore]
    );

    // Reset all filters
    const resetFilter = useCallback(() => {
        setPage(1);
        setKeyword('');
        setBoxStatusFilter(undefined);
        setPartyFilter(undefined);
        setAllData([]);
    }, []);

    // Box options for select
    const { data: defaultBoxOptions, refetch } = useRequest(
        () =>
            box_requests.getAll({
                partyId: partyFilter?.value,
            }),
        {
            enabled: !!partyFilter,
            selectData(data) {
                return data.data.data.data.map(p => ({ value: p.id, label: p.name }));
            },
            placeholderData: [],
            dependencies: [partyFilter],
        }
    );

    useEffect(() => {
        if (boxId && defaultPartyOptions && defaultPartyOptions.length > 0) {
            const selected = defaultPartyOptions.find(p => p.value === Number(boxId));
            if (selected) {
                setPartyFilter(selected);
            }
        }
    }, [boxId, defaultPartyOptions]);

    useEffect(() => {
        if (boxesIdAccepted) {
            navigation.push(`${pageLinks.dashboard.acceptance.index}?boxId=${boxesIdAccepted}`);
        }
    }, [boxesIdAccepted]);

    const onChangePrint = async (id: number, newStatus: PrintStatus) => {
        if (changeStatusIds.includes(id)) return;
        try {
            setChangeStatusIds(p => [...p, id]);
            const res = await box_requests.find({ packetId: id });
            await box_requests.update({
                cargoId: String(res.data.data.packet.cargoId),
                items: res.data.data.items,
                print: newStatus === 'true' ? true : false,
                packetId: String(res.data.data.packet.id),
                passportId: res.data.data.client.passportId,
                status: res.data.data.packet.status,
            });
            setPrintStatuses(prev => ({
                ...prev,
                [id]: newStatus,
            }));
        } catch (error) {
        } finally {
            setChangeStatusIds(prev => prev.filter(i => i !== id));
        }
    };

    // Filter changes with debouncing
    useEffect(() => {
        const debounceTimer = setTimeout(() => {
            if (page === 1) {
                getBoxesQuery.refetch();
            } else {
                setPage(1); // This will trigger the refetch automatically
            }
        }, 350);

        return () => clearTimeout(debounceTimer);
    }, [keyword, partyFilter?.value, boxFilter?.value]);

    // Fetch box amounts only when needed
    useEffect(() => {
        if (allData.length === 0 || loading) return;

        const controller = new AbortController();
        const fetchAmounts = async () => {
            const result: Record<number, { totalAmount: number; totalAccepted: number }> = {};

            try {
                await Promise.all(
                    allData.map(async box => {
                        if (boxAmounts[box.id]) return;

                        try {
                            const res = await box_requests.find({ packetId: box.id });
                            const boxData = res.data.data;

                            const total = boxData.items.reduce(
                                (acc, item) => {
                                    acc.totalAmount = boxData.packet.totalItems ?? 0;
                                    if (item.acceptedNumber && item.acceptedNumber > 0) {
                                        acc.totalAccepted += 1;
                                    }
                                    return acc;
                                },
                                { totalAmount: 0, totalAccepted: 0 }
                            );

                            result[box.id] = total;
                        } catch (e) {
                            if (!controller.signal.aborted) {
                                console.error(e);
                            }
                        }
                    })
                );

                if (Object.keys(result).length > 0) {
                    setBoxAmounts(prev => ({ ...prev, ...result }));
                }
            } catch (error) {
                console.error(error);
            }
        };

        fetchAmounts();

        return () => {
            controller.abort();
        };
    }, [allData, loading]);

    // Optimized scroll handler with throttling
    const handleScroll = useCallback(() => {
        if (!tableContainerRef.current || isFetching || !hasMore) return;

        const { scrollTop, scrollHeight, clientHeight } = tableContainerRef.current;
        const scrollThreshold = 100; // pixels from bottom to trigger load

        if (scrollHeight - (scrollTop + clientHeight) < scrollThreshold) {
            handleChange(page + 1);
        }
    }, [page, isFetching, hasMore, handleChange]);

    // Scroll event listener with cleanup
    useEffect(() => {
        const container = tableContainerRef.current;
        if (!container) return;

        const throttledScroll = throttle(handleScroll, 200);
        container.addEventListener('scroll', throttledScroll);

        return () => {
            container.removeEventListener('scroll', throttledScroll);
        };
    }, [handleScroll]);

    // Box options for select
    const boxOptions = (inputValue: string) => {
        return box_requests
            .getAll({
                cargoId: inputValue,
                partyId: partyFilter?.value,
            })
            .then(res => {
                return res.data.data.data.map(p => ({ label: p.name, value: p.id }));
            });
    };

    // Reset box filter when party changes
    useEffect(() => {
        setBoxFilter(undefined);
    }, [partyFilter]);

    // Table columns definition
    const columns: ColumnData<IBox>[] = useMemo(
        () => [
            {
                label: t('No'),
                width: 100,
                renderCell(data, rowIndex) {
                    return rowIndex + 1;
                },
            },
            {
                dataKey: 'partyName',
                label: t('party_name'),
                width: 120,
            },
            {
                dataKey: 'name',
                label: t('name'),
                width: 120,
            },
            {
                dataKey: 'packetNetWeight',
                label: t('weight'),
                width: 120,
            },
            {
                dataKey: 'totalItems',
                label: t('count_of_items'),
                width: 120,
                renderCell: data => {
                    const total = boxAmounts[data.id];

                    if (!total) return <Typography>...</Typography>;
                    const isCompleted = total.totalAmount === total.totalAccepted && total.totalAmount > 0;
                    return (
                        <Stack direction='row' alignItems='center' spacing={1}>
                            <Typography>
                                {data.totalItems} / {total.totalAccepted}
                            </Typography>
                            {isCompleted && <CheckCircle sx={{ color: '#22c55e', fontSize: 16 }} />}
                        </Stack>
                    );
                },
            },
            {
                dataKey: 'totalNetWeight',
                label: t('party_weight'),
                width: 120,
            },
            {
                dataKey: 'cargoId',
                label: t('cargo_id'),
                width: 120,
            },
            {
                dataKey: 'passportName',
                label: t('client'),
                width: 120,
            },
            {
                dataKey: 'id',
                label: t('print'),
                width: 120,
                renderHeaderCell() {
                    return (
                        <Stack direction={'row'} alignItems={'center'}>
                            <span>{t('print')}</span>
                        </Stack>
                    );
                },
                renderCell(data) {
                    const total = boxAmounts[data.id];
                    const isCompleted = total?.totalAccepted === total?.totalAmount && total?.totalAmount > 0;
                    return (
                        <Button onClick={() => onPrintBox(data)}>
                            <Print className='h-3 w-3 mr-1' />
                        </Button>
                    );
                },
            },
            {
                dataKey: 'status',
                label: t('status'),
                width: 240,
                renderHeaderCell() {
                    return (
                        <Stack direction={'row'} alignItems={'center'}>
                            <span>{t('print_status')}</span>
                        </Stack>
                    );
                },
                renderCell(data) {
                    const currentValue = printStatuses[data.id] || (data.print ? 'true' : 'false');
                    return (
                        <FormControl
                            sx={{ m: 1, border: 'none', minWidth: 120, background: data.print ? '#3489E4' : '#DF2F99' }}
                            size='small'
                        >
                            <Select
                                labelId={`print-status-${data.id}`}
                                id={`print-status-${data.id}`}
                                sx={{ color: 'white', border: 'none' }}
                                value={currentValue}
                                onChange={async e => {
                                    const newValue = e.target.value as PrintStatus;
                                    onChangePrint(data.id, newValue);
                                }}
                            >
                                <MenuItem value='true'>Chop etildi</MenuItem>
                                <MenuItem value='false'>Chop etilmadi</MenuItem>
                            </Select>
                        </FormControl>
                    );
                },
            },
            {
                label: '',
                width: 100,
                numeric: true,
                renderCell(data) {
                    return (
                        <ActionPopMenu
                            buttons={[
                                {
                                    icon: <RemoveRedEye sx={{ path: { color: '#3489E4' } }} />,
                                    label: t('view_packet'),
                                    onClick: () => {
                                        navigation.push(pageLinks.dashboard.boxes.detail(data.id));
                                    },
                                },
                            ]}
                        />
                    );
                },
            },
        ],
        [t, boxAmounts, printStatuses, navigation, onPrintBox, onChangePrint]
    );

    // Form handling for items
    const [items, setItems] = useState<Product>();
    const [loaer, setLoading] = useState(false);

    const {
        register,
        control,
        handleSubmit,
        watch,
        setValue,
        formState: { errors },
    } = useForm<Product>({
        defaultValues: {
            trekId: items?.trekId,
            name: items?.name,
            nameRu: items?.nameRu,
            amount: items?.amount,
            weight: items?.weight,
            acceptedNumber: Number(values),
        },
    });

    const updateItems = async (item: Product, acceptedNumber: number) => {
        try {
            setLoading(true);
            const updateBody: UpdateProductBodyType = {
                itemId: item.id,
                acceptedNumber: item.amount,
                amount: item.amount,
                name: item.name,
                nameRu: item.nameRu,
                trekId: item.trekId,
                weight: item.weight,
            };
            await item_requests.update(updateBody);
            getListQuery.refetch();
            setValues(prev => ({ ...prev, [item.trekId]: '' }));
            setTrackId('');
        } catch (error) {
            notifyUnknownError(error);
        } finally {
            setLoading(false);
        }
    };

    return (
        <Box>
            <CustomModal open={isModalOpen} onClose={closeModal} title={t('product_inspection')}>
                <Box sx={style}>
                    <Typography id='modal-modal-title' variant='h6' component='h2'>
                        {t('product_inspection')}
                    </Typography>
                    <Typography id='modal-modal-description' sx={{ mt: 2 }}>
                        {t('enter_product')}
                    </Typography>
                    <AsyncSelect
                        isClearable
                        value={partyFilter}
                        onChange={(newValue: any) => {
                            setPartyFilter(newValue);
                            setPage(1);
                        }}
                        styles={selectDefaultStyles}
                        noOptionsMessage={() => t('not_found')}
                        loadingMessage={() => t('loading')}
                        defaultOptions={defaultPartyOptions!}
                        loadOptions={partyOptions}
                        placeholder={t('filter_party_name')}
                    />
                    <AsyncSelect
                        isClearable
                        value={boxFilter}
                        onChange={(newValue: any) => {
                            setBoxFilter(newValue);
                            setPage(1);
                            navigation.push(pageLinks.dashboard.boxes.detail(newValue.value));
                        }}
                        styles={selectDefaultStyles}
                        noOptionsMessage={() => t('enter_box_name_to_find')}
                        loadingMessage={() => t('loading')}
                        defaultOptions={defaultBoxOptions!}
                        loadOptions={boxOptions}
                        placeholder={t('filter_box_name')}
                    />
                    <Button onClick={() => closeModal()} sx={{ position: 'absolute', right: '10px' }}>
                        <CloseIcon />
                    </Button>
                </Box>
            </CustomModal>

            <Stack direction={'row'} mb={3} spacing={3}>
                <Button onClick={() => openModal()}>{t('product_inspection')}</Button>
            </Stack>

            <Box
                width={1}
                mb={3}
                sx={{
                    padding: '28px',
                    borderRadius: '16px',
                    backgroundColor: '#fff',
                }}
            >
                <Stack mb={3.5} direction={'row'} justifyContent={'space-between'} alignItems={'center'}>
                    <Typography
                        sx={{
                            fontSize: '20px',
                            lineHeight: '24px',
                            fontWeight: 600,
                            textTransform: 'capitalize',
                            color: '#000',
                        }}
                    >
                        {t('packet')}
                    </Typography>
                    <Stack direction={'row'} alignItems={'center'} spacing={2}>
                        <BaseInput
                            InputProps={{
                                startAdornment: <Search color='primary' />,
                            }}
                            placeholder={t('filter_packet_name')}
                            value={keyword}
                            onChange={e => {
                                setKeyword(e.target.value);
                            }}
                        />
                        <AsyncSelect
                            isClearable
                            value={partyFilter}
                            onChange={(newValue: any) => {
                                setPartyFilter(newValue);
                                if (newValue) {
                                    setBoxIdAccepted(newValue.value);
                                    navigation.push(`${pageLinks.dashboard.acceptance.index}?boxId=${newValue.value}`);
                                } else {
                                    setBoxIdAccepted(undefined);
                                    navigation.push(`${pageLinks.dashboard.acceptance.index}`);
                                }
                                setPage(1);
                            }}
                            styles={selectDefaultStyles}
                            noOptionsMessage={() => t('not_found')}
                            loadingMessage={() => t('loading')}
                            defaultOptions={defaultPartyOptions!}
                            loadOptions={partyOptions}
                            placeholder={t('filter_party_name')}
                        />
                        <BaseButton colorVariant='gray' startIcon={<FilterListOff />} size='small' onClick={resetFilter}>
                            {t('reset_filter')}
                        </BaseButton>
                    </Stack>
                </Stack>

                <Box
                    mb={6}
                    ref={tableContainerRef}
                    sx={{
                        height: 'calc(100vh - 300px)',
                        overflowY: 'auto',
                        '&::-webkit-scrollbar': {
                            width: '6px',
                        },
                        '&::-webkit-scrollbar-thumb': {
                            backgroundColor: '#888',
                            borderRadius: '3px',
                        },
                    }}
                >
                    <MyTable columns={columns} data={allData} loading={loading && page === 1} />
                    {isFetching && page > 1 && (
                        <Box sx={{ display: 'flex', justifyContent: 'center', padding: '20px' }}>
                            <CircularProgress size={24} />
                        </Box>
                    )}
                </Box>
            </Box>
            {selectedBoxDetails && (
                <div style={{ display: 'none' }}>
                    <BoxesPrintList ref={printRef} boxData={selectedBoxDetails} />
                </div>
            )}
        </Box>
    );
};

// Simple throttle implementation
function throttle<T extends (...args: any[]) => any>(func: T, limit: number): T {
    let inThrottle: boolean;
    return function (this: any, ...args: any[]) {
        if (!inThrottle) {
            func.apply(this, args);
            inThrottle = true;
            setTimeout(() => (inThrottle = false), limit);
        }
    } as T;
}

export default DashboardAcceptancePage;
