import clsx from 'clsx';
import React, { PropsWithChildren } from 'react';
import { useResize } from '../../../hooks/useResize/useResize';
import { Data } from '../../../types/data';
import { DynamicListColumn } from '../DynamicDataList.model';
import classes from './DynamicListHeader.scss';

// TODO: Remove this data type, generic should actually be column type
export interface DynamicListHeaderProps<T extends Data> {
  /** Column definitions */
  columns: DynamicListColumn<T>[];
  /** Sizes of each column */
  columnSizes: string;
  /** Spacing between columns */
  columnGap?: string;
  /** Header row height */
  rowHeight?: string;
  /** Horizontal alignment of text */
  horizontalTextAlign?: 'left' | 'right' | 'center';
  /** Vertical alignment of text */
  verticalTextAlign?: 'start' | 'center' | 'end';
  /** Property name that is used to determine data position (default: undefined) */
  positionKey?: keyof T;
  /** If sets, sets the label for the position column (default: 'Position') */
  positionLabel?: string;
  /** If set to true, creates an empty column at the start of the header to line up with rows (default: undefined) */
  allowReordering?: boolean;
  /** CSS Class name for additional styles */
  className?: string;
  /** Whether header should stick to the top (default: true) */
  sticky?: boolean;
  /** If set to true, the position column will be shown (default: false) */
  showPositionColumn?: boolean;
  /** This will be used to determine the label for the position column if a positionLabel is not defined (default: false) */
  allowDragging?: boolean;
  /** If set to true, the action column will be shown (default: false) */
  showActionColumn?: boolean;
  /** called when the column sizes should be reset */
  onResetColumnSizes: () => void;
  /** called when the column sizes should be updated */
  onColumnSizesChanged: (columnSizes: string) => void;
}

export const DynamicListHeader = <T extends Data>({
  columns,
  columnSizes,
  columnGap,
  rowHeight,
  horizontalTextAlign,
  verticalTextAlign,
  positionLabel,
  className = '',
  sticky = true,
  showPositionColumn = false,
  allowDragging = false,
  showActionColumn,
  onColumnSizesChanged,
  onResetColumnSizes,
}: PropsWithChildren<DynamicListHeaderProps<T>>): JSX.Element => {
  const customStyles = {
    gridAutoRows: rowHeight,
    gridTemplateColumns: columnSizes,
    gridColumnGap: columnGap,
    justifyItems: horizontalTextAlign,
    alignItems: verticalTextAlign,
  } as React.CSSProperties;

  if (sticky) {
    customStyles.position = 'sticky';
    customStyles.top = 0;
  }

  const { cols, mouseDown, ResizeIndicator } = useResize(
    columns,
    onColumnSizesChanged,
  );

  return (
    <>
      {ResizeIndicator}
      <div
        className={clsx(
          classes.container,
          'dynamic-list-header-container',
          className,
        )}
        style={customStyles}
        data-test-id="dynamic-list-header"
      >
        {showPositionColumn && (
          <div
            className={clsx(classes.column)}
            data-test-id="dynamic-list-header-cell"
          >
            <p className={clsx(classes.position)}>
              {positionLabel ?? (allowDragging ? 'Position' : 'Pos')}
            </p>
            <div
              className={clsx(
                classes.resizeHandle,
                classes.resizeHandleDisabled,
              )}
            />
          </div>
        )}
        {columns.map((column, i) => (
          <div
            key={column.key ?? (column.propertyName as string)}
            className={clsx(classes.column)}
            ref={cols[i].ref}
            data-test-id={`dynamic-list-header-property:${
              column.propertyName as string
            }`}
          >
            <p>{column.label}</p>
            <div
              onMouseDown={
                !column.disableResizing
                  ? (e) => {
                      e.preventDefault();
                      mouseDown(i);
                    }
                  : undefined
              }
              onDoubleClick={onResetColumnSizes}
              className={clsx(classes.resizeHandle, {
                [classes.resizeHandleDisabled]: column.disableResizing ?? false,
              })}
            />
          </div>
        ))}
        {showActionColumn && (
          <div
            className={clsx(classes.column)}
            ref={cols[cols.length - 1].ref}
          />
        )}
      </div>
    </>
  );
};
