'use client';

import BaseButton from '@/components/ui-kit/BaseButton';
import BaseIconButton from '@/components/ui-kit/BaseIconButton';
import { useAuthContext } from '@/context/auth-context';
import { box_requests } from '@/data/box/box.requests';
import { item_requests } from '@/data/item/item.requests';
import { party_requests } from '@/data/party/party.requests';
import { FormValues, RealCreateBoxBodyType, UpdateRealBoxBodyType } from '@/data/real-box/real-box.model';
import { real_box_requests } from '@/data/real-box/real-box.requests';
import { pageLinks } from '@/helpers/constants';
import { useMyNavigation } from '@/hooks/useMyNavigation';
import { useMyTranslation } from '@/hooks/useMyTranslation';
import { notifyUnknownError } from '@/services/notification';
import { AddCircleRounded, Close } from '@mui/icons-material';
import {
    Box,
    Button,
    Checkbox,
    Chip,
    CircularProgress,
    FormControl,
    FormHelperText,
    Grid,
    InputLabel,
    ListItemText,
    MenuItem,
    OutlinedInput,
    Select,
    Stack,
    styled,
    Typography,
} from '@mui/material';
import { useQuery } from '@tanstack/react-query';
import get from 'lodash.get';
import { useSearchParams } from 'next/navigation';
import { useEffect, useRef, useState } from 'react';
import { Controller, useFieldArray, useForm } from 'react-hook-form';

const StyledCreateBox = styled(Box)`
    .item-row {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 16px;
    }

    & > * {
        flex: 1 1 1;
    }
`;

interface Props {
    partiesData?: { value: number; label: string }[];
    initialValues?: {
        id?: number;
        boxId?: string;
        partyId?: number;
        partyName?: string;
        paketIds?: Array<any>;
    };
}

const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => {
    const { user } = useAuthContext();
    const editMode = !!initialValues?.id;
    const t = useMyTranslation();
    const params = useSearchParams();
    const { push } = useMyNavigation();
    const [partyId, setPartyId] = useState<number | string>('');
    const [loading, setLoading] = useState(false);

    const {
        control,
        handleSubmit,
        setValue,
        reset,
        watch,
        formState: { errors },
    } = useForm<FormValues>({
        defaultValues: {
            partyName: initialValues?.partyName || '',
            packetItemDtos: initialValues?.paketIds
                ? initialValues.paketIds.map(paket => ({
                      packetId: paket.id,
                      itemDtos: paket.items ? paket.items.map((item: any) => item.id) : [],
                  }))
                : params.get('party_id')
                  ? [{ packetId: +params.get('party_id')!, itemDtos: [] }]
                  : [{ packetId: 0, itemDtos: [] }],
            id: initialValues?.id,
            boxId: initialValues?.boxId,
            partyId: initialValues?.partyId,
        },
    });

    useEffect(() => {
        if (initialValues) {
            reset({
                partyName: initialValues.partyName || '',
                packetItemDtos: initialValues.paketIds
                    ? initialValues.paketIds.map(paket => ({
                          packetId: paket.id,
                          itemDtos: paket.items ? paket.items.map((item: any) => item.id) : [],
                      }))
                    : [{ packetId: 0, itemDtos: [] }],
                id: initialValues.id,
                boxId: initialValues.boxId,
                partyId: initialValues.partyId,
            });
            if (initialValues.partyId) {
                setPartyId(initialValues.partyId);
            }
        }
    }, [initialValues, reset]);

    const { fields, append, remove } = useFieldArray({
        control,
        name: 'packetItemDtos',
        keyName: 'key',
    });

    const requiredText = t('required');

    const { data: parties = [], isLoading: isLoadingParties } = useQuery({
        queryKey: ['parties-list', 'COLLECTING'],
        queryFn: () => party_requests.getAll({ status: 'COLLECTING' }),
        select: data =>
            data.data.data.data.map((p: any) => ({
                id: p.id,
                name: p.name,
            })),
    });

    const onSubmit = handleSubmit(async values => {
        try {
            setLoading(true);

            if (editMode) {
                const updateBody: UpdateRealBoxBodyType = {
                    boxId: initialValues!.boxId!,
                    partyName: values.partyName,
                    packetItemDtos: values.packetItemDtos.map(packet => ({
                        packetId: packet.packetId,
                        itemDtos: packet.itemDtos,
                    })),
                };
                await real_box_requests.update(updateBody);
            } else {
                const createBody: RealCreateBoxBodyType = {
                    partyName: values.partyName,
                    packetItemDtos: values.packetItemDtos.map(packet => ({
                        packetId: packet.packetId,
                        itemDtos: packet.itemDtos,
                    })),
                };
                await real_box_requests.create(createBody);
            }

            push(pageLinks.dashboard.real_boxes.index);
        } catch (error) {
            notifyUnknownError(error);
        } finally {
            setLoading(false);
        }
    });

    const handlePacketChange = (index: number, value: number) => {
        setValue(`packetItemDtos.${index}.packetId`, value);
        setValue(`packetItemDtos.${index}.itemDtos`, []);
    };

    const appendPacket = () => {
        append({ packetId: 0, itemDtos: [] });
    };

    const removePacket = (index: number) => {
        remove(index);
    };
    const [packetSearchTerm, setPacketSearchTerm] = useState('');

    const packetSearchInputRef = useRef<HTMLInputElement>(null);

    const handlePartyChange = (event: any) => {
        const selectedParty = parties.find(p => p.id === event.target.value);
        if (selectedParty) {
            setValue('partyName', selectedParty.name);
            setPartyId(selectedParty.id);
            setValue('packetItemDtos', [{ packetId: 0, itemDtos: [] }]);
        }
    };

    const [paketName, setPaketName] = useState<string>('');
    const PacketRow = ({ index, field }: { index: number; field: any }) => {
        const packetId = watch(`packetItemDtos.${index}.packetId`);
        const [itemsPage, setItemsPage] = useState(1);
        const [itemsList, setItemsList] = useState<any[]>([]);
        const [itemsHasMore, setItemsHasMore] = useState(true);
        const itemScrollRef = useRef<HTMLDivElement>(null);
        const [packetsPage, setPacketsPage] = useState(1);
        const [packetsList, setPacketsList] = useState<any[]>([]);
        const [packetsHasMore, setPacketsHasMore] = useState(true);
        const [selectedProductNames, setSelectedProductNames] = useState<{ [packetIndex: number]: { [productId: number]: string } }>({});
        const [paketName, setPaketName] = useState<string>('');
        const [lastPacketId, setLastPacketId] = useState<number | null>(null);

        const { isLoading: isLoadingProducts } = useQuery({
            queryKey: ['product-list', packetId, itemsPage],
            queryFn: () => item_requests.getAll({ packetId, page: itemsPage }),
            enabled: !!packetId,
            onSuccess: data => {
                const newItems = data?.data?.data?.data || [];
                setItemsList(prev => (itemsPage === 1 ? newItems : [...prev, ...newItems]));
            },
        });

        const packetScrollRef = useRef<HTMLDivElement>(null);
        const [keyword, setKeyword] = useState<string>('');
        const { isFetching: isLoadingPackets } = useQuery({
            queryKey: ['packets-list', partyId, keyword, packetsPage],
            queryFn: () => box_requests.getAll({ partyId, cargoId: keyword, page: packetsPage }),
            enabled: !!partyId,
            onSuccess: data => {
                const newPackets = data?.data?.data?.data || [];
                setPacketsList(prev => (packetsPage === 1 ? newPackets : [...prev, ...newPackets]));
                const totalPages = data?.data?.data?.totalPages || 0;
                setPacketsHasMore(packetsPage < totalPages);
            },
        });

        const handlePacketScroll = (e: React.UIEvent<HTMLDivElement>) => {
            const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;
            const isNearBottom = scrollHeight - scrollTop - clientHeight < 50;

            if (isNearBottom && !isLoadingPackets && packetsHasMore) {
                setPacketsPage(prev => prev + 1);
            }
        };

        const handleItemScroll = (e: React.UIEvent<HTMLDivElement>) => {
            const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;
            const isNearBottom = scrollHeight - scrollTop - clientHeight < 50;

            if (isNearBottom && !isLoadingProducts && itemsHasMore) {
                setItemsPage(prev => prev + 1);
            }
        };

        const handleProductChange = (packetIndex: number, product: any, checked: boolean) => {
            setSelectedProductNames(prev => {
                const prevNames = prev[packetIndex] || {};
                if (checked) {
                    return { ...prev, [packetIndex]: { ...prevNames, [product.id]: product.name || product.nameRu || String(product.id) } };
                } else {
                    const newNames = { ...prevNames };
                    delete newNames[product.id];
                    return { ...prev, [packetIndex]: newNames };
                }
            });
        };

        const handleSelectAllProducts = async () => {
            if (!packetId) return;
            let allProducts: any[] = [];
            let page = 1;
            let totalPages = 1;
            try {
                do {
                    const res = await item_requests.list({ packetId, page });
                    const data = res?.data?.data;
                    const products = data?.data || [];
                    totalPages = data?.totalPages || 1;
                    allProducts = [...allProducts, ...products];
                    page++;
                } while (page <= totalPages);
            } catch (e) {
                // error silent
            }
            if (allProducts.length > 0) {
                setValue(
                    `packetItemDtos.${index}.itemDtos`,
                    allProducts.map((p: any) => p.id)
                );
                setSelectedProductNames((prev: any) => ({
                    ...prev,
                    [index]: allProducts.reduce(
                        (acc, p) => ({
                            ...acc,
                            [p.id]: p.name || p.nameRu || String(p.id),
                        }),
                        {}
                    ),
                }));
            }
        };

        const handleClearAll = () => {
            setValue(`packetItemDtos.${index}.itemDtos`, []);
            setSelectedProductNames((prev: any) => ({ ...prev, [index]: {} }));
        };

        return (
            <Box className='item-row' mb={2} display={'flex'} flexDirection={'column'}>
                <div style={{ width: '100%' }}>
                    <Typography fontSize='18px' sx={{ textAlign: 'start' }} fontWeight={500} color='#5D5850'>
                        {t('packet')}
                    </Typography>
                </div>
                <Box
                    className='item-row-field'
                    sx={{ width: '100%' }}
                    flex={1}
                    display={'flex'}
                    gap={2}
                    justifyContent={'space-between'}
                    alignItems={'center'}
                >
                    <OutlinedInput onChange={e => setKeyword(e.target.value)} />
                    <div style={{ width: '100%' }}>
                        <FormControl fullWidth>
                            <InputLabel id={`packet-select-label-${index}`}>{t('packet')}</InputLabel>
                            <Controller
                                name={`packetItemDtos.${index}.packetId`}
                                control={control}
                                rules={{ required: requiredText }}
                                render={({ field }) => (
                                    <>
                                        <Select
                                            {...field}
                                            labelId={`packet-select-label-${index}`}
                                            label={t('packet')}
                                            value={field.value || ''}
                                            disabled={isLoadingPackets}
                                            renderValue={selected =>
                                                paketName || packetsList.find(p => p.id === selected)?.name || t('select')
                                            }
                                            MenuProps={{
                                                PaperProps: {
                                                    style: { maxHeight: 280 },
                                                    ref: packetScrollRef,
                                                    onScroll: handlePacketScroll,
                                                },
                                                disableAutoFocus: true,
                                                autoFocus: false,
                                            }}
                                            onClick={e => e.stopPropagation()}
                                            onChange={e => {
                                                field.onChange(e);
                                                const selected = packetsList.find(p => p.id === e.target.value);
                                                setPaketName(selected?.name || '');
                                            }}
                                        >
                                            {isLoadingPackets && packetsList.length === 0 ? (
                                                <MenuItem disabled>
                                                    <CircularProgress size={24} />
                                                </MenuItem>
                                            ) : (
                                                packetsList.map(packet => (
                                                    <MenuItem key={packet.id} value={packet.id} onClick={() => setPaketName(packet.name)}>
                                                        {packet.name}
                                                    </MenuItem>
                                                ))
                                            )}
                                            {isLoadingPackets && packetsList.length > 0 && (
                                                <MenuItem disabled>
                                                    <CircularProgress size={20} />
                                                </MenuItem>
                                            )}
                                        </Select>
                                    </>
                                )}
                            />
                            {!!get(errors, `packetItemDtos.${index}.packetId`) && (
                                <FormHelperText sx={{ color: 'red' }}>{requiredText}</FormHelperText>
                            )}
                        </FormControl>
                    </div>
                    <div>
                        {fields.length > 1 && (
                            <BaseIconButton
                                size='small'
                                colorVariant='icon-error'
                                sx={{ flexShrink: 0, height: 'auto', marginTop: 1 }}
                                onClick={() => removePacket(index)}
                            >
                                <Close />
                            </BaseIconButton>
                        )}
                    </div>
                </Box>

                {packetId && (
                    <Box mt={2} sx={{ width: '100%' }}>
                        <Box display='flex' justifyContent='space-between' alignItems='center' mb={2}>
                            <Typography fontSize='18px' sx={{ textAlign: 'start' }} fontWeight={500} color='#5D5850'>
                                {t('products')}
                            </Typography>
                            <Box>
                                <Button size='small' color='primary' variant='outlined' sx={{ mr: 1 }} onClick={handleSelectAllProducts}>
                                    {t('select_all') || 'Barcha mahsulotni tanlash'}
                                </Button>
                                <Button size='small' color='error' variant='outlined' onClick={handleClearAll}>
                                    {t('cancel') || 'Hammasini bekor qilish'}
                                </Button>
                            </Box>
                        </Box>
                        {isLoadingProducts && itemsList.length === 0 ? (
                            <CircularProgress />
                        ) : (
                            <FormControl fullWidth>
                                <Controller
                                    name={`packetItemDtos.${index}.itemDtos`}
                                    control={control}
                                    render={({ field }) => (
                                        <Select
                                            {...field}
                                            multiple
                                            MenuProps={{
                                                PaperProps: {
                                                    style: { maxHeight: 280 },
                                                    ref: itemScrollRef,
                                                    onScroll: handleItemScroll,
                                                },
                                                disableAutoFocus: true,
                                                autoFocus: false,
                                            }}
                                            renderValue={selected => (
                                                <Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 0.5 }}>
                                                    {(selected as any[]).map(id => {
                                                        return (
                                                            <Chip
                                                                key={id}
                                                                label={
                                                                    selectedProductNames[index]?.[id] ||
                                                                    itemsList.find(p => p.id === id)?.name ||
                                                                    itemsList.find(p => p.id === id)?.nameRu ||
                                                                    id
                                                                }
                                                                onDelete={e => {
                                                                    e.stopPropagation();
                                                                    field.onChange(field.value.filter((x: any) => x !== id));
                                                                    handleProductChange(index, { id }, false);
                                                                }}
                                                            />
                                                        );
                                                    })}
                                                </Box>
                                            )}
                                        >
                                            {itemsList.map(product => (
                                                <MenuItem
                                                    key={product.id}
                                                    value={product.id}
                                                    onClick={e => {
                                                        e.stopPropagation();
                                                        const checked = !field.value.includes(product.id);
                                                        let newValue;
                                                        if (checked) {
                                                            newValue = [...field.value, product.id];
                                                        } else {
                                                            newValue = field.value.filter((x: any) => x !== product.id);
                                                        }
                                                        field.onChange(newValue);
                                                        handleProductChange(index, product, checked);
                                                    }}
                                                >
                                                    <Checkbox checked={field.value.includes(product.id)} />
                                                    <ListItemText primary={product.name || product.nameRu || product.id} />
                                                </MenuItem>
                                            ))}
                                        </Select>
                                    )}
                                />
                            </FormControl>
                        )}
                    </Box>
                )}
            </Box>
        );
    };

    return (
        <StyledCreateBox
            width={1}
            mb={3}
            sx={{
                padding: '28px',
                borderRadius: '16px',
                backgroundColor: '#fff',
            }}
        >
            <Box component='form' onSubmit={onSubmit}>
                <Typography variant='h5' mb={3.5}>
                    {editMode ? t('update_box') : t('create_box')}
                </Typography>

                <Grid container columnSpacing={2.5} rowSpacing={3} mb={3.5}>
                    <Grid item xs={12}>
                        <Typography fontSize='18px' fontWeight={500} color='#5D5850' mb={2}>
                            {t('party_name')}
                        </Typography>
                        <FormControl fullWidth>
                            <InputLabel id='party-select-label'>{t('party_name')}</InputLabel>
                            <Controller
                                name='partyId'
                                control={control}
                                rules={{ required: requiredText }}
                                render={({ field }) => (
                                    <Select
                                        {...field}
                                        labelId='party-select-label'
                                        label={t('party_name')}
                                        onChange={e => {
                                            field.onChange(e);
                                            handlePartyChange(e);
                                        }}
                                        value={field.value || ''}
                                        disabled={isLoadingParties}
                                    >
                                        {isLoadingParties ? (
                                            <MenuItem disabled>
                                                <CircularProgress size={24} />
                                            </MenuItem>
                                        ) : (
                                            parties.map(party => (
                                                <MenuItem key={party.id} value={party.id}>
                                                    {party.name}
                                                </MenuItem>
                                            ))
                                        )}
                                    </Select>
                                )}
                            />
                            {!!errors.partyId && <FormHelperText sx={{ color: 'red' }}>{requiredText}</FormHelperText>}
                        </FormControl>
                    </Grid>

                    <Grid item xs={12}>
                        <Stack
                            sx={{
                                borderRadius: '8px',
                                border: '2px solid #3489E4',
                                background: '#FFF',
                                padding: '24px',
                                gap: '12px',
                                display: 'flex',
                                flexDirection: 'column',
                            }}
                        >
                            <div>
                                {fields.map((field, index) => (
                                    <PacketRow key={field.key} index={index} field={field} />
                                ))}
                                <BaseButton variant='outlined' onClick={appendPacket} startIcon={<AddCircleRounded />} sx={{ mt: 2 }}>
                                    {t('add_packet')}
                                </BaseButton>
                            </div>
                        </Stack>
                    </Grid>
                </Grid>

                <BaseButton variant='contained' type='submit' disabled={loading} fullWidth sx={{ py: 1.5 }}>
                    {loading ? <CircularProgress size={24} color='inherit' /> : editMode ? t('update_box') : t('create_box')}
                </BaseButton>
            </Box>
        </StyledCreateBox>
    );
};

export default DashboardCreateRealBoxPage;
