import {
    forwardRef,
    useEffect,
    useImperativeHandle,
    useMemo,
    useRef,
    useState,
} from 'react';

import _ from 'lodash';
import {
    ChartLineIcon,
    ChartPieIcon,
    FunnelIcon,
    ListOrderedIcon,
    PlusCircle,
    SquareMIcon,
    TableRowsSplit,
} from 'lucide-react';
import { AiOutlineFunnelPlot } from 'react-icons/ai';

import { rpc } from '@/api/request';
import {
    BiAggregateEnum,
    BiBlockEnum,
    BiBlockType,
    BiBlockValueType,
    BiGroupTransformEnum,
    StructureType,
} from '@/api/types';
import TableFilterDialog, {
    TableFilterDialogRef,
} from '@/components/CollectionTable/components/TableFilterDialog';
import { Button } from '@/components/ui/button';
import {
    Dialog,
    DialogContent,
} from '@/components/ui/dialog';
import {
    Grid,
    GridCol,
    GridRow,
} from '@/components/ui/grid';
import { Input } from '@/components/ui/input';
import {
    Item,
    ItemActions,
    ItemContent,
    ItemDescription,
    ItemMedia,
    ItemTitle,
} from '@/components/ui/item';
import { Label } from '@/components/ui/label';
import {
    Select,
    SelectContent,
    SelectGroup,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import { Lang } from '@/lang/Lang';

import BIBlockView from './BIBlockView';

const Block = ({ children }: { children: React.ReactNode }) => {

    return <div className='mb-4'>
        {children}
    </div>
}


const getBiBlockName = (type: BiBlockEnum) => {
    return Lang.key(`bi_block_type_${type}_name`);
}

const getBiBlockDescription = (type: BiBlockEnum) => {
    return Lang.key(`bi_block_type_${type}_description`);
}


const itemsTypeList: {
    type: BiBlockEnum;
    icon: React.ReactNode;

}[] = [
        {

            type: "chart",
            icon: <ChartLineIcon size={30} />,

        },

        {
            type: "pie",
            icon: <ChartPieIcon size={30} />,
        },

        {
            type: "table",
            icon: <ListOrderedIcon size={30} />,
        },
        {
            type: "square",
            icon: <SquareMIcon size={30} />,
        },
        {
            type: "funnel",
            icon: <AiOutlineFunnelPlot size={30} />,
        },
        {

            type: "abc",
            icon: <TableRowsSplit size={30} />,
        },
        {
            type: "xyz",
            icon: <TableRowsSplit size={30} />,
        },
    ]



type OpenParams = {
    data?: BiBlockType;
    onSave: (data: BiBlockType) => void;

}

export type BIBlockDialogRef = {
    open: (params: OpenParams) => void;
    close: () => void;
}

const aggregateTypeList: {
    [key in BiAggregateEnum]: string
} = {
    countRoot: "Общее количество",

    sum: "Сумма",
    avg: "Среднее значение",
    min: "Минимальное значение",
    max: "Максимальное значение",
}

const BIBlockDialog = forwardRef<BIBlockDialogRef, {}>((params, ref) => {

    const [open, setOpen] = useState(false);


    const [allCollections, setAllCollections] = useState<StructureType[]>([]);

    const [selectedCollection, setSelectedCollection] = useState<StructureType | null>(null);


    const tableFilterDialogRef = useRef<TableFilterDialogRef>(null);


    const [data, setData] = useState<BiBlockType | null>(null);


    const onSaveRef = useRef<((data: BiBlockType) => void) | null>(null);
    useImperativeHandle(ref, () => ({
        open: (params: OpenParams) => {



            if (params.data) {
                setData(params.data);
            } else {
                setData(null);
            }

            onSaveRef.current = params.onSave;



            setOpen(true);
        },

        close: () => {
            setOpen(false);
        }
    }));


    useEffect(() => {
        if (data?.source && allCollections.length > 0) {
            let find = allCollections.find((collection) => collection.collection === data?.source);
            if (find) {
                setSelectedCollection(find);
            }
        }
    }, [data?.source, allCollections]);


    useEffect(() => {

        if (selectedCollection) {
            setData((prev) => {
                return { ...prev, source: selectedCollection?.collection };
            })
        }

    }, [selectedCollection]);

    useEffect(() => {


        if (open) {
            rpc.allCollections().then((res) => {
                setAllCollections(res?.result ?? []);


            });
        }
    }, [open]);



    const groupByFields = useMemo((): StructureType[] => {

        let _groupByFields: StructureType[] = [];

        _.forEach(selectedCollection?.items, (item) => {

            if (item.inAdmin && !item.hide) {
                _groupByFields.push(item);
            }
        });

        return _groupByFields;
    }, [selectedCollection]);

    const valueFields = useMemo((): StructureType[] => {

        if (data?.aggregateType == "countRoot") {
            return [];
        }

        let _valueFields: StructureType[] = [];
        _.forEach(selectedCollection?.items, (item) => {
            if (item.inAdmin && !item.hide && item.key != data?.groupByField) {


                if (item.type == "int" || item.type == "float") {

                    _valueFields.push(item);
                }


            }
        });
        return _valueFields;
    }, [selectedCollection, data?.aggregateType]);


    const [valuesData, setValuesData] = useState<BiBlockValueType | null>(null);

    useEffect(() => {

        if (data?.source && data?.groupByField && data?.aggregateType) {
            rpc.calculateBiBlock(data).then((res) => {
                setValuesData(res?.result ?? null);
            }).catch((err) => {
                console.error('Error calculating bi block:', err);
                setValuesData(null);
            });
        } else {
            setValuesData(null);
        }

    }, [data?.source, data?.groupByField, data?.aggregateType, data?.valueField, data?.filter, data?.groupTransform]);


    const groupTransformList = useMemo((): Record<BiGroupTransformEnum, string> => {

        let _groupTransformList: Record<BiGroupTransformEnum, string> = {} as Record<BiGroupTransformEnum, string>;


        let _groupByField = groupByFields.find((item) => item.key == data?.groupByField);

        if (_groupByField?.type == "unixdate" || _groupByField?.type == "unixdatetime") {

            _groupTransformList["hour"] = "Час";
            _groupTransformList["day"] = "День";
            _groupTransformList["month"] = "Месяц";
            _groupTransformList["year"] = "Год";
            _groupTransformList["week"] = "Неделя";


        }

        // _.forEach(groupByFields, (item) => {
        //    _groupTransformList[item.key!] = item.title!;
        // });

        return _groupTransformList;


        //  return ["day", "month", "year", "week", "quarter"];
    }, [data?.groupByField]);

    return <><Dialog open={open}

        onOpenChange={setOpen}
    >

        <DialogContent className="!w-[80vw] !max-w-[80vw] sm:!max-w-[80vw] h-[80vh] overflow-hidden !p-0" >


            {!!data?.type ? <Grid className='h-full w-full !w-[80vw] !max-w-[80vw] sm:!max-w-[80vw] h-[80vh]'>
                <GridCol className='px-3  py-4 border-r'>

                    <GridRow className='flex flex-col '>
                        <div>

                            <Block>
                                <Label>Название</Label>
                                <Input value={data?.title ?? ""} onChange={(e) => setData((prev) => {
                                    return { ...prev, title: e.target.value };
                                })} />
                            </Block>
                            <Block>

                                <Label>Исходные данные</Label>
                                <Select value={selectedCollection?.collection!} onValueChange={(value) => {
                                    setSelectedCollection(allCollections.find((collection) => collection.collection === value) ?? null);
                                }}>
                                    <SelectTrigger className="w-full">
                                        <SelectValue placeholder="Выберите источник данных" />
                                    </SelectTrigger>
                                    <SelectContent>
                                        <SelectGroup>
                                            {allCollections.map((collection) => {
                                                return <SelectItem value={collection.collection!}>{collection.title}</SelectItem>
                                            })}
                                        </SelectGroup>
                                    </SelectContent>
                                </Select>


                            </Block>

                            <Block>
                                <Button
                                    className='w-full'
                                    variant={_.size(data?.filter ?? {}) > 0 ? "default" : "outline"}
                                    onClick={() => tableFilterDialogRef.current?.open()}><FunnelIcon /> Фильтры ({_.size(data?.filter ?? {})})</Button>
                            </Block>


                            {selectedCollection && <>


                                {(data.type == "chart" || data.type == "pie" || data.type == "table" || data.type == "funnel" || data.type == "abc" || data.type == "xyz") && <>
                                    <Block>

                                        <Label>Группировка</Label>
                                        <Select
                                            value={data?.groupByField ?? undefined}
                                            onValueChange={(value) => setData((prev) => {
                                                return { ...prev, groupByField: value };
                                            })}
                                        >
                                            <SelectTrigger className="w-full">
                                                <SelectValue placeholder="Выберите поле" />
                                            </SelectTrigger>
                                            <SelectContent>
                                                <SelectGroup>
                                                    {groupByFields.map((item) => {
                                                        return <SelectItem value={item.key!}>{item.title}</SelectItem>
                                                    })}
                                                </SelectGroup>
                                            </SelectContent>
                                        </Select>


                                    </Block>

                                    {_.size(groupTransformList) > 0 && <Block>

                                        <Label>Формирование поля группировки</Label>
                                        <Select
                                            value={data?.groupTransform ?? undefined}
                                            onValueChange={(value) => setData((prev) => {
                                                return { ...prev, groupTransform: value as BiGroupTransformEnum };
                                            })}
                                        >
                                            <SelectTrigger className="w-full">
                                                <SelectValue placeholder="Выберите поле" />
                                            </SelectTrigger>
                                            <SelectContent>
                                                <SelectGroup>
                                                    {_.map(groupTransformList, (value, key) => {
                                                        return <SelectItem value={key}>{value}</SelectItem>
                                                    })}
                                                </SelectGroup>
                                            </SelectContent>
                                        </Select>


                                    </Block>}

                                </>}


                                <Block>

                                    <Label>Агрегация</Label>
                                    <Select
                                        value={data?.aggregateType ?? undefined}
                                        onValueChange={(value) => setData((prev) => {
                                            return { ...prev, aggregateType: value as BiAggregateEnum };
                                        })}
                                    >
                                        <SelectTrigger className="w-full">
                                            <SelectValue placeholder="Выберите агрегацию" />
                                        </SelectTrigger>
                                        <SelectContent>
                                            <SelectGroup>
                                                {_.map(aggregateTypeList, (value, key) => {
                                                    return <SelectItem value={key}>{value}</SelectItem>
                                                })}
                                            </SelectGroup>
                                        </SelectContent>
                                    </Select>


                                </Block>


                                {valueFields.length > 0 && <Block>

                                    <Label>Целевое поле агрегации</Label>
                                    <Select
                                        value={data?.valueField ?? undefined}
                                        onValueChange={(value) => setData((prev) => {
                                            return { ...prev, valueField: value as BiAggregateEnum };
                                        })}
                                    >
                                        <SelectTrigger className="w-full">
                                            <SelectValue placeholder="Выберите поле" />
                                        </SelectTrigger>
                                        <SelectContent>
                                            <SelectGroup>
                                                {valueFields.map((item) => {
                                                    return <SelectItem value={item.key!}>{item.title}</SelectItem>
                                                })}
                                            </SelectGroup>
                                        </SelectContent>
                                    </Select>


                                </Block>}



                            </>}

                        </div>



                    </GridRow>
                </GridCol>
                <GridCol>


                    <BIBlockView
                        colSpan={12}
                        rowSpan={1}
                        item={data ?? {}}
                    />

                    <GridRow autoSize>
                        <Button onClick={() => {
                            if (data) {
                                onSaveRef.current?.(data);
                                setOpen(false);
                            }

                        }}>{Lang.key('save')}</Button>

                        <Button
                            variant="outline"

                            onClick={() => {
                                setOpen(false);
                            }}>{Lang.key('cancel')}</Button>
                    </GridRow>





                </GridCol>

            </Grid> : <div>

                {itemsTypeList.map((item) => {
                    return <Item variant="outline">
                        <ItemMedia>
                            <div className='mr-3'>
                                {item.icon}
                            </div>

                        </ItemMedia>
                        <ItemContent>
                            <ItemTitle>{getBiBlockName(item.type)}</ItemTitle>
                            <ItemDescription>{getBiBlockDescription(item.type)}</ItemDescription>
                        </ItemContent>
                        <ItemActions>
                            <Button

                                onClick={() => {

                                    setData((prev) => {
                                        return { ...prev, type: item.type };
                                    });

                                }}

                                size="icon-sm"
                                variant="outline"
                                className="rounded-full"

                            >
                                <PlusCircle size={30} />
                            </Button>
                        </ItemActions>
                    </Item>
                })}


            </div>}



        </DialogContent>
    </Dialog>

        <TableFilterDialog
            onApply={(data, values) => {
                setData((prev) => {
                    return { ...prev, filter: values };
                });
            }}
            initialFilter={data?.filter ?? {}}
            structure={selectedCollection}

            ref={tableFilterDialogRef}
        />

    </>


});

export default BIBlockDialog;