import { ReactNode, createContext, useContext, useMemo } from 'react';

import { CommonProps } from '../../../types';
import type { TableProps } from '../Table';

/** Values of {@link TablePropsContext} */
export type TablePropsContextValue = Omit<TableProps<any, any>, 'children' | keyof CommonProps> & {
  children: ReactNode;
};

const TablePropsContext = createContext<TablePropsContextValue | undefined>(undefined);

/** Context that provides table props inside table */
export function TablePropsContextProvider({
  rows,
  rowIdProvider,
  columns,
  totalRows,
  selection,
  onSelectionChanged,
  sort,
  onSortChanged,
  loading,
  rowSelectionEnabled,
  rowSelectionIncludeLimit,
  rowSelectionName,
  rowActionsEnabled,
  stickyColumns,
  children,
}: TablePropsContextValue) {
  const value = useMemo<TablePropsContextValue>(
    () => ({
      rows,
      rowIdProvider,
      columns,
      totalRows,
      selection,
      rowSelectionName,
      onSelectionChanged,
      sort,
      onSortChanged,
      loading,
      rowSelectionEnabled,
      rowSelectionIncludeLimit,
      rowActionsEnabled,
      stickyColumns,
      children,
    }),
    [
      children,
      columns,
      loading,
      onSelectionChanged,
      onSortChanged,
      rowActionsEnabled,
      stickyColumns,
      rowIdProvider,
      rowSelectionEnabled,
      rowSelectionIncludeLimit,
      rowSelectionName,
      rows,
      selection,
      sort,
      totalRows,
    ],
  );

  return <TablePropsContext.Provider value={value}>{children}</TablePropsContext.Provider>;
}

/** Returns current table props */
export function useTablePropsContext(): TablePropsContextValue {
  const value = useContext(TablePropsContext);
  if (!value) {
    throw new Error('useTablePropsContext should be used only inside TablePropsContextProvider');
  }

  return value;
}
