import _ from 'lodash';
import { PlusCircle } from 'lucide-react';

import type {
    AllFieldsEnum,
    StructureType,
} from '@/api/types';
import { MenuData } from '@/components/AnyDropdownMenu';
import { LL } from '@/lang/LL';

import TableItem from './components/TableItem/TableItem';

export type ColumnsType = {
    key: string;
    dataIndex: string;
    sorter: boolean;
    width: number;
    showSorterTooltip: boolean;
    render: (value: any, record: any) => React.ReactNode;
    title: () => React.ReactNode;
    children?: ColumnsType[];
}

export const getColumnsInternal = (
    sorter: boolean,
    structure: StructureType,
    keyPrefix: string = '',
    titlePrefix: string[] = [],
    keyPathPrefix: string[] = [],
): ColumnsType[] => {
    let columns: ColumnsType[] = [];

    const splitKey = ' → ';

    if (!structure) return columns;

    const items = _(structure.items ?? {})
        .toPairs()
        .orderBy(([_, value]) => value.tablePriority || 0, 'desc')
        .fromPairs()
        .value();

    _.map(items, (item) => {
        if (item.inAdmin && item.inTable && !item.hide) {
            const itemKey = item.key!;
            const itemKeyPath = [...keyPathPrefix, itemKey];
            const localizedTitle = item.title ?? item.key ?? '';

            if (item.type == "structure" || item.type == "range") {
                let children = getColumnsInternal(
                    false,
                    item,
                    `${keyPrefix}${itemKey}.`,
                    [...titlePrefix, localizedTitle],
                    itemKeyPath,
                );

                children.map((child) => {
                    columns.push({
                        ...child,
                    })
                });
                return;
            }

            columns.push({
                key: keyPrefix + itemKey,
                dataIndex: keyPrefix + itemKey,
                sorter: true,
                width: item.columnsWidth ?? 150,
                showSorterTooltip: false,
                render: (valueItem: any, record: any) => {
                    let value = _.get(record, keyPrefix + itemKey);

                    return <TableItem
                        structure={item ?? null}
                        value={value}
                    />
                },
                title: () => {
                    let length = localizedTitle.length;
                    let title = '';

                    if (length > 2) {
                        title = localizedTitle;
                    } else {
                        title = [...titlePrefix, localizedTitle].join(splitKey);
                    }

                    return <div className="text-xs truncate ..."><LL value={title} /></div>
                },
            });
        }
    });

    return columns;
};

type MenuByFilterStructureParams = {
    titlePrefix?: string[];
    onSelect?: (structure: StructureType) => void;
    structure: StructureType | null;
    selectBefore: string[];
    rootStructure?: StructureType;

}

const transformStructure = (
    structure: StructureType,
    path: string[],
    rootStructure: StructureType,

    accumulatedPath: string[] = [],
): StructureType => {
    if (path.length === 0) {
        return structure;
    }

    let firstPath = path[0];

    let includeStructure = { ...structure.items?.[firstPath] };

    if (!includeStructure) {
        return structure;
    }

    const childPath = [...accumulatedPath, firstPath];
    const parentTitle = accumulatedPath.length === 0
        ? (rootStructure.title ?? rootStructure.collection ?? '')
        : structure.title ?? structure.key ?? '';
    const childTitle = includeStructure.title ?? includeStructure.key ?? '';

    includeStructure.title = `${parentTitle} → ${childTitle}`;

    if (structure.key) {
        includeStructure.key = `${structure.key}.${includeStructure.key}`;
    } else {
        includeStructure.key = includeStructure.key;
    }

    includeStructure.col = 24;

    return transformStructure(includeStructure, path.slice(1), rootStructure, childPath);
}

export const flatFilterStructure = ({
    structure,
    selectBefore,
    rootStructure,
}: {
    structure: StructureType;
    selectBefore?: string[];
    rootStructure?: StructureType;
}): StructureType[] => {
    if (!structure) return [];

    if (!rootStructure) {
        rootStructure = structure;
    }

    if (!selectBefore) {
        selectBefore = [];
    }
    let result: StructureType[] = [];

    _.map(structure.items, (item, key) => {
        if (item.hide) return;
        if (!item.inAdmin) return;
        if (!item.editable) return;

        if (item.items) {
            result.push(...flatFilterStructure({
                structure: item,
                selectBefore: [...selectBefore, item.key!],
                rootStructure: rootStructure,
            }));
        } else {
            result.push(transformStructure(rootStructure!, [...selectBefore, item.key!], rootStructure!));
        }
    })

    return result;
}

export const menuByFilterStructure = ({
    onSelect,
    structure,
    selectBefore,
    titlePrefix,
    rootStructure,
}: MenuByFilterStructureParams) => {
    if (!structure) return [];

    if (structure.hide) return [];

    if (!rootStructure) {
        rootStructure = structure;
    }

    let menu: MenuData[] = [];

    _.map(structure.items, (item, key) => {
        if (item.hide) return;
        if (!item.inAdmin) return;
        if (!item.editable) return;



        const itemKeyPath = [...selectBefore, item.key!];
        const label = item.title ?? item.key;

        if (item.items) {
            menu.push({
                label: <LL value={label ?? item.key ?? ''} />,
                htmlIcon: <PlusCircle />,
                submenu: menuByFilterStructure({
                    onSelect: onSelect,
                    structure: item,
                    selectBefore: itemKeyPath,
                    rootStructure: rootStructure,
                }),
            })
        } else {
            menu.push({
                label: <LL value={label ?? item.key ?? ''} />,
                htmlIcon: <PlusCircle />,
                click: () => {
                    let _selectBefore = itemKeyPath;
                    let newStructure = transformStructure(rootStructure!, _selectBefore, rootStructure!);
                    onSelect?.(newStructure);
                }
            })
        }
    })

    return menu;
}

export const prepareFilterValues = (values: any) => {
    let result: any = {};

    _.forEach(values, (value, key) => {
        let keys = key.split('.');
        _.set(result, keys, value);
    });

    return result;
}

export const structureHaveType = (type: AllFieldsEnum, structure: StructureType | null): boolean => {
    if (!structure) return false;

    let have = false;

    _.map(structure.items, (field, key) => {
        if (field.type === type) {
            have = true;
        }
    });

    return have;
}
