'use client';

import BaseButton from '@/components/ui-kit/BaseButton';
import BaseIconButton from '@/components/ui-kit/BaseIconButton';
import { party_requests } from '@/data/party/party.requests';
import { box_requests } from '@/data/box/box.requests';
import { real_box_requests } from '@/data/real-box/real-box.requests';
import { pageLinks } from '@/helpers/constants';
import { notifyUnknownError } from '@/services/notification';
import { Box, FormHelperText, Grid, Stack, Typography, styled } from '@mui/material';
import { AddCircleRounded, Close } from '@mui/icons-material';
import { useSearchParams } from 'next/navigation';
import React, { useEffect, useMemo, useRef, useState } from 'react';
import { Controller, useFieldArray, useForm } from 'react-hook-form';
import AsyncSelect from 'react-select/async';
import { selectDefaultStyles } from '@/components/ui-kit/BaseReactSelect';
import { useAuthContext } from '@/context/auth-context';
import { useMyNavigation } from '@/hooks/useMyNavigation';
import { useMyTranslation } from '@/hooks/useMyTranslation';
import { FormValues, RealCreateBoxBodyType, UpdateRealBoxBodyType } from '@/data/real-box/real-box.model';
import get from 'lodash.get';
import useRequest from '@/hooks/useRequest';

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<{ id: number; packetName: string }>;
    };
}

const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => {
    const { user, isAdmin: isAdminUser } = 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 helperRef = useRef<{
        finished: boolean;
        partyFinished: boolean;
        clientFinished: boolean;
        settedDefaultParty: any;
    }>({
        settedDefaultParty: null,
        partyFinished: false,
        clientFinished: false,
        finished: false,
    });

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

    // Reset form when initialValues change (for edit mode)
    useEffect(() => {
        if (initialValues) {
            reset({
                partyName: initialValues.partyName || '',
                paketIds: initialValues.paketIds
                    ? initialValues.paketIds.map((paket) => ({ id: paket.id }))
                    : [{ id: '' }],
                id: initialValues.id,
                boxId: initialValues.boxId,
                partyId: initialValues.partyId,
            });
            if (initialValues.partyId) {
                setPartyId(initialValues.partyId);
            }
        }
    }, [initialValues, reset]);

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

    const requiredText = t('required');

    const getBoxesQuery = useRequest(
        () =>
            box_requests.getAll({
                partyId: partyId,
            }),
        {
            selectData: (data) => data?.data?.data ?? [],
            enabled: !!partyId,
        },
    );

    const list = useMemo(() => {
        return getBoxesQuery.data?.data.filter((box: any) => box.status === 'READY_TO_INVOICE') ?? [];
    }, [getBoxesQuery.data]);

    useEffect(() => {
        if (partyId) {
            getBoxesQuery.refetch();
        }
    }, [partyId, getBoxesQuery.refetch]);

    const { data: defaultParties } = useRequest(
        () => party_requests.getAll({ status: 'COLLECTING' }),
        {
            enabled: true,
            selectData: (data) =>
                data.data.data.data.map((p: any) => ({ value: p.id, label: p.name })),
            onSuccess: (data) => {
                if (!editMode && data?.data?.data?.data?.[0]) {
                    const defaultParty = data.data.data.data[0];
                    helperRef.current.settedDefaultParty = defaultParty;
                    setValue('partyName', defaultParty.name);
                    setValue('paketIds.0.id', defaultParty.id); // Use dot notation
                    setPartyId(defaultParty.id);
                }
                helperRef.current.partyFinished = true;
                if (helperRef.current.clientFinished) {
                    helperRef.current.finished = true;
                }
            },
            placeholderData: [],
        },
    );

    const onSubmit = handleSubmit(async (values) => {
        try {
            setLoading(true);
            const packetDtos = values.paketIds.map((paket) => Number(paket.id)).filter((id) => id);

            if (editMode) {
                const updateBody: UpdateRealBoxBodyType = {
                    boxId: initialValues!.boxId!,
                    partyName: values.partyName,
                    packetDtos,
                };
                await real_box_requests.update(updateBody);
            } else {
                const createBody: RealCreateBoxBodyType = {
                    partyName: values.partyName,
                    packetDtos,
                };
                await real_box_requests.create(createBody);
            }

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

    const partyOptions = async (inputValue: string) => {
        try {
            const res = await party_requests.getAll({
                status: 'COLLECTING',
                partyName: inputValue,
            });
            return res.data.data.data.map((p: any) => ({ label: p.name, value: p.id }));
        } catch (error) {
            notifyUnknownError(error);
            return [];
        }
    };

    const appendPaket = () => {
        append({ id: '' });
    };

    const removePaket = (index: number) => {
        remove(index);
    };

    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>
                        <Controller
                            name="partyName"
                            control={control}
                            rules={{ required: requiredText }}
                            render={({ field }) => (
                                <AsyncSelect
                                    onChange={(newValue: any) => {
                                        field.onChange(newValue?.label ?? '');
                                        setPartyId(newValue?.value ?? '');
                                    }}
                                    defaultValue={
                                        editMode
                                            ? {
                                                value: initialValues?.partyId,
                                                label: initialValues?.partyName,
                                            }
                                            : partiesData?.length
                                                ? {
                                                    value: partiesData[0].value,
                                                    label: partiesData[0].label,
                                                }
                                                : null
                                    }
                                    styles={selectDefaultStyles}
                                    noOptionsMessage={() => t('not_found')}
                                    loadingMessage={() => t('loading')}
                                    onBlur={field.onBlur}
                                    name={field.name}
                                    defaultOptions={defaultParties ?? []}
                                    loadOptions={partyOptions}
                                    placeholder={t('enter_party_name_to_find')}
                                />
                            )}
                        />
                        {!!errors.partyName && (
                            <FormHelperText sx={{ color: 'red' }}>{requiredText}</FormHelperText>
                        )}
                    </Grid>

                    <Grid item xs={12}>
                        <Stack
                            sx={{
                                borderRadius: '8px',
                                border: '2px solid #3489E4',
                                background: '#FFF',
                                padding: '24px',
                            }}
                        >
                            <Typography fontSize="18px" fontWeight={500} color="#5D5850" mb={2}>
                                {t('packet')}
                            </Typography>
                            {fields.map((field, index) => (
                                <Box key={field.key} className="item-row" mb={2}>
                                    <Box className="item-row-field" flex={1}>
                                        <Controller
                                            name={`paketIds.${index}.id`}
                                            control={control}
                                            rules={{ required: requiredText }}
                                            render={({ field: paketField }) => (
                                                <AsyncSelect
                                                    onChange={(newValue: any) => {
                                                        paketField.onChange(newValue?.value ?? '');
                                                    }}
                                                    defaultValue={
                                                        editMode && initialValues?.paketIds?.[index]
                                                            ? {
                                                                value: initialValues.paketIds[index].id,
                                                                label:
                                                                    initialValues.paketIds[index].packetName ||
                                                                    `Box ${initialValues.paketIds[index].id}`,
                                                            }
                                                            : null
                                                    }
                                                    styles={selectDefaultStyles}
                                                    noOptionsMessage={() => t('not_found')}
                                                    loadingMessage={() => t('loading')}
                                                    onBlur={paketField.onBlur}
                                                    name={paketField.name}
                                                    defaultOptions={list.map((box: any) => ({
                                                        value: box.id,
                                                        label: box.box_name || box.name || `Box ${box.id}`,
                                                    }))}
                                                    loadOptions={async (inputValue: string) => {
                                                        if (!partyId) return [];
                                                        try {
                                                            const res = await box_requests.getAll({
                                                                partyId,
                                                            });
                                                            return res.data.data.data.map((box: any) => ({
                                                                label: box.box_name || box.name || `Box ${box.id}`,
                                                                value: box.id,
                                                            }));
                                                        } catch (error) {
                                                            notifyUnknownError(error);
                                                            return [];
                                                        }
                                                    }}
                                                    placeholder={t('enter_box_name_to_find')}
                                                />
                                            )}
                                        />
                                        {!!get(errors, `paketIds.${index}.id`) && (
                                            <FormHelperText sx={{ color: 'red' }}>{requiredText}</FormHelperText>
                                        )}
                                    </Box>
                                    {fields.length > 1 && (
                                        <Box className="item-row-field">
                                            <BaseIconButton
                                                size="small"
                                                colorVariant="icon-error"
                                                sx={{ flexShrink: 0, height: 'auto', marginTop: 1 }}
                                                onClick={() => removePaket(index)}
                                            >
                                                <Close />
                                            </BaseIconButton>
                                        </Box>
                                    )}
                                </Box>
                            ))}
                            <Stack alignItems="center" mt={2}>
                                <BaseButton
                                    sx={{ backgroundColor: '#239D5F' }}
                                    startIcon={<AddCircleRounded />}
                                    onClick={appendPaket}
                                >
                                    {t('add_more')}
                                </BaseButton>
                            </Stack>
                        </Stack>
                    </Grid>
                </Grid>

                <BaseButton type="submit" colorVariant="blue" loading={loading}>
                    {editMode ? t('update') : t('create')}
                </BaseButton>
            </Box>
        </StyledCreateBox>
    );
};

export default DashboardCreateRealBoxPage;