import React from "react";
import {
  ColumnOrderState,
  flexRender,
  Row,
  Table,
} from "@tanstack/react-table";
import {
  CraftTableFeatureProps,
  CraftTableOptionsProps,
} from "../../types/table-options";
import { align } from "../../types/common";
import DragAlongCell from "./table-body-dnd-cell";
import {
  horizontalListSortingStrategy,
  SortableContext,
} from "@dnd-kit/sortable";
import { getColumnPinningStylesBody } from "../../libs/utils/common";
import Checkbox from "../inputs/checkbox";
import { TableBodyCell, TableBodyRow } from "./table-body.styles";

interface TableBodyProps<T> {
  table: Table<T>;
  featureOptions: CraftTableFeatureProps;
  NestedComponent?: React.ComponentType<{ row: Row<T> }>;
  columnOrder: ColumnOrderState;
  tableStates: CraftTableOptionsProps;
}

function TableBody<T>({
  table,
  featureOptions,
  NestedComponent,
  columnOrder,
  tableStates,
}: TableBodyProps<T>) {
  const { enableColumnReordering, enableRowSelection } = featureOptions;

  const { wrapColumns } = tableStates;

  const renderRow = (row: Row<T>) => {
    const renderedRow = (
      <TableBodyRow
        key={row?.id}
        hoverable
        striped={featureOptions.striped}
        selected={row.getIsSelected()}
        expanded={row.getIsExpanded()}
      >
        {enableRowSelection && (
          <TableBodyCell
            style={{
              position: "sticky",
              left: 0,
              width: "50px",
            }}
          >
            <Checkbox
              checked={row.getIsSelected()}
              indeterminate={row.getIsSomeSelected()}
              onChange={row.getToggleSelectedHandler()}
              className="checkbox__input"
            />
          </TableBodyCell>
        )}

        {row?.getVisibleCells()?.map((cell) => {
          return enableColumnReordering ? (
            <SortableContext
              key={cell.id}
              items={columnOrder}
              strategy={horizontalListSortingStrategy}
            >
              <DragAlongCell
                cell={cell}
                featureOptions={featureOptions}
                tableStates={tableStates}
              />
            </SortableContext>
          ) : (
            <TableBodyCell
              style={{
                ...getColumnPinningStylesBody(cell.column),
                width: cell.column.getSize(),
                ...((wrapColumns.all_wrap || wrapColumns[cell.column.id]) && {
                  wordBreak: "break-all",
                  whiteSpace: "normal",
                }),
              }}
              className="table-row-cell"
              align={(cell.column.columnDef.meta as align)?.align || "left"}
            >
              {flexRender(cell?.column?.columnDef?.cell, cell?.getContext())}
            </TableBodyCell>
          );
        })}
      </TableBodyRow>
    );

    if (row.getIsExpanded()) {
      return (
        <React.Fragment key={row.id}>
          {renderedRow}
          {NestedComponent && (
            <TableBodyRow
              hoverable
              striped={featureOptions.striped}
              selected={row.getIsSelected()}
              expanded={row.getIsExpanded()}
            >
              {<NestedComponent {...{ row }} />}
            </TableBodyRow>
          )}
        </React.Fragment>
      );
    } else {
      return renderedRow;
    }
  };

  return (
    <tbody>{table?.getRowModel()?.rows?.map((row) => renderRow(row))}</tbody>
  );
}

export default TableBody;
