import { useCallback, useContext, useEffect, useMemo, useRef, } from 'react';
import { ConfigContext } from '../../ConfigProvider';
import { useFirstMountState } from '../../useFirstMountState';
import { prop } from '../../utils/prop';
import { uniqueBy } from '../../utils/uniqueBy';
import { dataGridClassnames } from '../constants';
import { Variant } from '../enums';
import { getDataGridCssVars, getFlattenColumns, getGridTemplateColumns, isGroupColumns, } from '../utils';
import { useDataGridMobileLogic, usePinnedColumns } from './hooks';
import { getIsAllowHorizontalScroll } from './utils';
export const useLogic = ({ keyId, columns, rows = [], variant, tree, subrows, selectedRows = [], isLoading, isDisabled, onSelectRow, isError, onRetry, errorMsg, isHideSelectAll, isHideHeaderIfNoData = false, sorting, className, onSort, maxHeight, gridViewMode: gridViewModeProp = 'standard', }) => {
    const isFirstRender = useFirstMountState();
    const isSelectable = Boolean(onSelectRow);
    const isDataGridDisabled = isLoading || isDisabled;
    const { imagesMap } = useContext(ConfigContext);
    // Реф добавлен для избежания замыкания selectedRows в handleSelectRow (иначе в handleSelectRow приходят некорректные значения selectedRows).
    const selectedRowsRef = useRef(selectedRows);
    useEffect(() => {
        selectedRowsRef.current = selectedRows;
    }, [selectedRows]);
    const prevRowsRef = useRef([]);
    useEffect(() => {
        if (!isLoading) {
            prevRowsRef.current = rows;
        }
    }, [rows, isLoading]);
    const processedColumns = useCallback(() => {
        if (rows.length <= 1) {
            return columns.map((column) => ({ ...column, sortable: false }));
        }
        return columns;
    }, [columns, rows]);
    const renderRows = isLoading ? prevRowsRef.current : rows;
    const isNoData = !renderRows.length;
    const { containerRef, rowHoverProps, sections, hasPinnedColumns } = usePinnedColumns({
        isLoading,
        columns: processedColumns(),
    });
    const { isMobile, mobileSkeletonProps } = useDataGridMobileLogic({
        containerRef,
        isLoading,
        columns: getFlattenColumns(processedColumns()),
        rows,
        isNoScrollToTop: isLoading && isNoData,
    });
    const treeRenderConfig = Object.is(variant, Variant.Subrows)
        ? { ...subrows, isInitialExpanded: true }
        : tree;
    const availableRows = rows.filter((row) => !(row.options?.isDisabled || row.options?.isNotSelectable));
    const gridColumns = useMemo(() => getGridTemplateColumns(getFlattenColumns(columns)), [columns]);
    const isAllowHorizontalScroll = getIsAllowHorizontalScroll(getFlattenColumns(columns));
    const uncheckedRowsCount = useMemo(() => {
        return availableRows.filter((row) => !selectedRows.find((selectedRow) => selectedRow[keyId] === row[keyId])).length;
    }, [availableRows, selectedRows, keyId]);
    const handleSelectAllRows = (event) => {
        if (!onSelectRow) {
            return;
        }
        if (event.target.checked) {
            const mergedSelectedRows = uniqueBy([...selectedRows, ...availableRows], prop(keyId));
            return onSelectRow(mergedSelectedRows);
        }
        const filteredRows = selectedRows.filter((selectedRow) => !rows.find((row) => row[keyId] === selectedRow[keyId]));
        onSelectRow(filteredRows);
    };
    const handleSelectRow = (row) => (event) => {
        if (!onSelectRow) {
            return;
        }
        if (event.target.checked) {
            return onSelectRow([...selectedRowsRef.current, row]);
        }
        onSelectRow(selectedRowsRef.current.filter((selectedRow) => selectedRow[keyId] !== row[keyId]));
    };
    const hasGroupedColumns = columns.some(isGroupColumns);
    const gridViewMode = hasGroupedColumns ? 'full' : gridViewModeProp;
    const isHideHead = (isHideHeaderIfNoData && isNoData) || (hasGroupedColumns && isNoData);
    const contentStateProps = useMemo(() => {
        return {
            isLoading: (isLoading && isNoData) || (isMobile && isLoading),
            isError: isError && isNoData,
            loadingTitle: 'Загрузка данных',
            errorState: {
                imgAlt: 'Что-то пошло не так',
                errorList: [errorMsg || ''],
                imgSrc: imagesMap.defaultErrorImgSrc,
                onRetry,
            },
            isSmoothLoading: false,
            loadingPlaceholderClassname: dataGridClassnames.loadingPlaceholder,
        };
    }, [isLoading, isError, isNoData, errorMsg, onRetry, imagesMap]);
    const containerCssVars = getDataGridCssVars(maxHeight);
    return {
        dataGridClassName: className,
        containerCssVars,
        isDataGridDisabled,
        treeRenderConfig,
        renderRows,
        isAllowHorizontalScroll,
        isHideHead,
        hasPinnedColumns,
        contentStateProps,
        rowHoverProps,
        isMobile,
        containerRef,
        gridColumns,
        isNoData,
        gridViewMode,
        headColumns: processedColumns(),
        isLoading,
        mobileSkeletonProps,
        hasGroupedColumns,
        headProps: {
            rowsCount: availableRows.length,
            uncheckedRowsCount,
            isSelectable,
            onSelectAllRows: handleSelectAllRows,
            isHideSelectAll,
            sorting,
            onSort,
        },
        bodyProps: {
            isSelectable,
            onSelectRow: handleSelectRow,
        },
        sections,
        loaderProps: {
            isLoading: !isFirstRender && isLoading,
            isVisibleDivider: Boolean(rows.length),
            isDisabled,
        },
    };
};
