import {
  type Row as TanstackRow,
  type RowData,
  flexRender,
} from '@tanstack/react-table';
import React, { useCallback, useMemo, useState } from 'react';
import { Collapse } from '../../atoms';
import type { CellAlign } from '../../utils/get-cell-align';

export type ExpandComp<Datum> = React.FC<{ row: TanstackRow<Datum> }>;
export type OnRowClick<Datum> = (data: Datum) => void;

interface RowProps<Datum extends RowData> {
  row: TanstackRow<Datum>;
  ExpandComp?: ExpandComp<Datum>;
  onRowClick?: OnRowClick<Datum>;
  gridTemplateColumns: string;
  getRowStyle?: (data: Datum) => React.CSSProperties;
  getCellStyle?: (data: Datum) => React.CSSProperties;
  defaultAlign: CellAlign;
}

export function Row<Datum extends RowData>(
  props: RowProps<Datum>
): React.ReactNode {
  const { row, ExpandComp, gridTemplateColumns, getRowStyle, getCellStyle } =
    props;
  const [open, setOpen] = useState(false);

  const onClickRow = useCallback(() => {
    props.onRowClick?.(row.original);
    setOpen((prev) => !prev);
  }, [props, row.original]);

  const rowClassName = useMemo(() => {
    const baseCls = ['tr-wrapper'];
    if (ExpandComp) {
      baseCls.push('expandable');
    }
    if (props.onRowClick) {
      baseCls.push('clickable');
    }
    return baseCls.join(' ');
  }, [ExpandComp, props.onRowClick]);

  return (
    <div className={rowClassName} key={`tr-wrapper_${row.id}`}>
      <button
        className="tr"
        key={`tr_${row.id}`}
        onClick={onClickRow}
        style={{
          gridTemplateColumns,
          ...(getRowStyle?.(row.original) || {}),
        }}
        type="button"
      >
        {row.getVisibleCells().map((cell) => {
          const autoSize = cell.column.columnDef.meta?.autoSize;
          const justifyContent =
            cell.column.columnDef.meta?.align || props.defaultAlign;

          return (
            <div
              className="td"
              key={cell.id}
              style={{
                // width: autoSize ? undefined : cell.column.getSize(),
                flexGrow: autoSize ? 1 : undefined,
                justifyContent,
                ...(getCellStyle?.(row.original) || {}),
              }}
            >
              {flexRender(cell.column.columnDef.cell, cell.getContext())}
              {cell.column.columnDef.meta?.OpenBtn ? (
                <cell.column.columnDef.meta.OpenBtn
                  data={row.original}
                  open={open}
                  setIsOpen={setOpen}
                />
              ) : null}
            </div>
          );
        })}
      </button>
      {ExpandComp ? (
        <Collapse open={open}>
          <div className="expand-comp-wrapper">
            <ExpandComp row={row} />
          </div>
        </Collapse>
      ) : null}
    </div>
  );
}
