import React, { useEffect } from 'react';

import type { GridlerColumns } from '../Column';

import { type FilterOption, type SortOption, useGridlerStore } from '../GridlerStore';

export interface GlidlerLocalDataAdaptorProps<T = unknown> {
  data: Array<T>;
  onColumnFilter?: (
    colFilters: Array<FilterOption> | undefined,
    cols: GridlerColumns | undefined,
    data: Array<T>
  ) => Array<T>;
  onColumnSort?: (
    colSort: Array<SortOption> | undefined,
    cols: GridlerColumns | undefined,
    data: Array<T>
  ) => Array<T>;
  onSearch?: (
    searchField: string | undefined,
    cols: GridlerColumns | undefined,
    data: Array<T>
  ) => Array<T>;
}

//The computer component does not need to be recalculated on every render, so we use React.memo to prevent unnecessary re-renders.
function _GlidlerLocalDataAdaptor<T = unknown>(props: GlidlerLocalDataAdaptorProps<T>) {
  const [setState, getState, mounted] = useGridlerStore((s) => [s.setState, s.getState, s.mounted]);

  const { colFilters, colSort, columns, searchStr } = useGridlerStore((s) => ({
    colFilters: s.colFilters,
    colOrder: s.colOrder,
    colSize: s.colSize,
    colSort: s.colSort,
    columns: s.columns,
    searchStr: s.searchStr,
  }));

  const refChanged = React.useRef({
    colFilters: colFilters,
    colSort: colSort,
    searchStr: searchStr,
  });

  const useAPIQuery: (index: number) => Promise<any> = async (index: number) => {
    const pageSize = getState('pageSize');

    if (!(props.data && Array.isArray(props.data))) {
      return [];
    }

    setState('total_rows', props.data.length);
    return props.data.slice(index * (pageSize ?? 50), (index + 1) * (pageSize ?? 50));
  };

  useEffect(() => {
    setState('useAPIQuery', useAPIQuery);
  }, [mounted, setState]);

  useEffect(() => {
    if (props.onColumnSort && colSort !== refChanged?.current?.colSort) {
      const sortedData = props.onColumnSort(colSort, columns, props.data as Array<T>);
      setState('total_rows', sortedData.length);
      setState('data', sortedData);
      refChanged.current.colSort = colSort;
      getState('refreshCells')?.();
    }
  }, [colSort, props.onColumnSort]);

  useEffect(() => {
    if (props.onColumnFilter && colFilters !== refChanged?.current?.colFilters) {
      const filteredData = props.onColumnFilter(colFilters, columns, props.data as Array<T>);
      setState('total_rows', filteredData.length);
      setState('data', filteredData);
      refChanged.current.colFilters = colFilters;
      getState('refreshCells')?.();
    }
  }, [colFilters, props.onColumnFilter]);

  useEffect(() => {
    if (props.onSearch && searchStr !== refChanged?.current?.searchStr) {
      const filteredData = props.onSearch(searchStr, columns, props.data as Array<T>);
      setState('total_rows', filteredData.length);
      setState('data', filteredData);
      refChanged.current.colFilters = colFilters;
      getState('refreshCells')?.();
    }
  }, [searchStr, props.onSearch]);

  return <></>;
}
export const GlidlerLocalDataAdaptor = React.memo(_GlidlerLocalDataAdaptor);

GlidlerLocalDataAdaptor.displayName = 'Gridler-GlidlerLocalDataAdaptor';
