import { observer } from 'mobx-react-lite';
import React, {
  forwardRef,
  HTMLAttributes,
  MutableRefObject,
  useEffect,
  useState,
} from 'react';
import { classes, st } from './NestedTableRow.st.css.js';
import { FiltersMap } from '@wix/bex-core';
import { Table } from '@wix/design-system';
import type { NestedTableDragAndDrop } from '../NestedTableDragAndDrop/NestedTableDragAndDrop';
import { NestedTableDataItem } from '../../state/NestedTableState/NestedTableNodeState';

export interface NestedTableRowProps<C extends string, T, F extends FiltersMap>
  extends HTMLAttributes<HTMLTableRowElement> {
  item: NestedTableDataItem<C, T, F>;
  dragAndDrop?: typeof NestedTableDragAndDrop;
}

const _NestedTableRow = forwardRef(
  <C extends string, T, F extends FiltersMap>(
    props: NestedTableRowProps<C, T, F> & { rowData: unknown },
    ref:
      | ((instance: HTMLTableRowElement | null) => void)
      | MutableRefObject<HTMLTableRowElement | null>
      | null,
  ) => {
    const { children, item, className, rowData, dragAndDrop, ...rest } = props;

    const [itemState] = useState(() => {
      return item.state.createNode({
        parent: item.originalKeyedItem,
      });
    });

    useEffect(() => itemState?.init(), []);

    const { st: dataTableRowSt, classes: dataTableRowClasses } =
      Table.dataTableRowStyle;

    const expandable =
      itemState != null &&
      !itemState._isNotExpandableWhenEmpty &&
      !item.state._isExpandableActionDisabled(item.originalKeyedItem.item);

    const isRowHighlight = item.state.levelDescriptor.isRowHighlight?.(
      item.originalKeyedItem.item,
    );

    const isSameEntityAsOtherLevels =
      itemState?.levelDescriptor.isSameEntityAsOtherLevels;
    let child = (
      <tr
        {...(process.env.NODE_ENV !== 'production' && {
          'data-parent-key': item.state.parent?.key,
          'data-index-in-parent': item.originalKeyedItem.indexWithinPage,
        })}
        {...(process.env.NODE_ENV === 'test' && {
          'data-virtual-direct-children-count':
            item.state.collection.result.size,
          'data-level': item.state.childrenDepth,
          'data-indentation-width': item.state.nestedTable._indentationWidth,
        })}
        ref={ref}
        className={st(
          classes.root,
          {
            expandable,
          },
          isRowHighlight ? dataTableRowClasses.dataTableHighlight : undefined,
          item.state.showHoverHighlight ? classes.parentHovered : undefined,
          item.state.childrenDepth === 0 && !isSameEntityAsOtherLevels
            ? classes.firstLevel
            : undefined,
          dataTableRowSt(dataTableRowClasses.root, {
            skin:
              item.state.childrenDepth === 0 && !isSameEntityAsOtherLevels
                ? 'neutral'
                : 'light',
          }),
          className,
        )}
        onMouseEnter={() => {
          itemState?._changeHover(true);
        }}
        onMouseLeave={() => {
          itemState?._changeHover(false);
        }}
        {...rest}
        onClick={(ev) => {
          rest?.onClick?.(ev);
          if (expandable) {
            itemState._toggleExpand();
            itemState.bi.reportExpandCollapse();
          }
        }}
      >
        {children}
      </tr>
    );

    if (dragAndDrop) {
      const { NestedTableDragAndDropRow } = dragAndDrop;
      child = (
        <NestedTableDragAndDropRow item={item} forwardedRef={ref}>
          {child}
        </NestedTableDragAndDropRow>
      );
    }

    return child;
  },
);

export const NestedTableRow = observer(_NestedTableRow);
