import React, { forwardRef, MutableRefObject, useMemo, useState } from 'react';
import {
  Box,
  SkeletonGroup,
  SkeletonLine,
  Table,
  TableProps,
} from '@wix/design-system';
import { FiltersMap } from '@wix/bex-core';
import { ResponsiveColumnsState, ToolbarCollectionState } from '../../state';
import { observer } from 'mobx-react-lite';

export interface TableSkeletonProps<T, F extends FiltersMap> {
  state: ToolbarCollectionState<T, F>;
  dataHook?: string;
  rowsCount?: number;
  showTitleBar?: boolean;
  rowVerticalPadding?: TableProps['rowVerticalPadding'];
}

export function _TableSkeleton<T, F extends FiltersMap>(
  props: TableSkeletonProps<T, F>,
) {
  const { state, dataHook, rowsCount = 7, showTitleBar, ...rest } = props;

  const [{ columnCount, minItemWidth, itemsContentWidth }] = useState(
    () =>
      new ResponsiveColumnsState({
        gridState: {
          gap: 24,
        },
        minItemWidth: 192,
        rectState: state.toolbarRect,
        containerPadding: 48,
      }),
  );

  const data = useMemo(
    () =>
      new Array(rowsCount)
        .fill(null)
        .map((_, i) => ({ id: `skeleton-row-${i}` })),
    [rowsCount],
  );

  const columns = useMemo(
    () =>
      new Array(columnCount).fill(null).map((_, i) => ({
        title: '',
        key: `skeleton-column-${i}`,
        dataHook: `skeleton-column-${i}`,
        render: () => (
          <Box direction="vertical" width="100%" minWidth={`${minItemWidth}px`}>
            <SkeletonGroup>
              <SkeletonLine width="100%" marginTop="SP1" marginBottom="SP1" />
            </SkeletonGroup>
          </Box>
        ),
      })),
    [columnCount],
  );

  const [TrElementType] = useState(() =>
    forwardRef(
      (
        { rowData: _rowData, ...trProps }: { rowData?: unknown },
        ref:
          | ((instance: HTMLTableRowElement | null) => void)
          | MutableRefObject<HTMLTableRowElement | null>
          | null,
      ) => {
        // <TableSkeleton/> is rendered inside the main <Table/> component, so we need to remove the data-table-row attribute from the <tr/> element to make testkit not to consider skeleton rows as real rows
        return <tr ref={ref} {...trProps} data-table-row={undefined} />;
      },
    ),
  );
  if (!itemsContentWidth && process.env.NODE_ENV !== 'test') {
    return null;
  }
  return (
    // <Box/> wrapper always aligns the skeleton to the top of the table
    <Box marginBottom="auto" dataHook={dataHook}>
      <Table
        skin="neutral"
        data={data}
        columns={columns}
        withWrapper={false}
        {...{ TrElementType }}
        {...rest}
      >
        <Box
          direction="vertical"
          backgroundColor="D80"
          borderRadius="0px 0px 8px 8px"
          overflow="hidden"
        >
          <Table.Content
            titleBarVisible={showTitleBar && state.collection.showInitialLoader}
          />
        </Box>
      </Table>
    </Box>
  );
}

export const TableSkeleton = observer(_TableSkeleton);
