import type { ReactNode, RefAttributes, CSSProperties } from "react";
import classNames from "classnames/dedupe";
import type { DOMProps } from "../../types/dom";
import { filterUndefinedProps, getSpacingValue } from "../../utils";
import type { SpacingType } from "../../types";

export type GridElementType = HTMLDivElement;

export interface GridProps extends RefAttributes<GridElementType>, DOMProps {
  children?: ReactNode;
  /** The number of columns */
  columns?: number;
  /** How big a gap between the columns and rows */
  gap?: SpacingType;
  /** How big a gap between the columns */
  columnGap?: SpacingType;
  /** How big a gap between the rows */
  rowGap?: SpacingType;
  /** Aligns the grid along the block (column) axis */
  alignContent?:
    | "center"
    | "space-around"
    | "space-between"
    | "space-evenly"
    | "stretch";
  /** Aligns the grid along the inline (row) axis */
  justifyContent?:
    | "center"
    | "start"
    | "end"
    | "space-around"
    | "space-between"
    | "space-evenly";
  /** Aligns grid items along the block (column) axis  */
  alignItems?: "center" | "start" | "end" | "stretch" | "baseline";
  /** Aligns grid items along the inline (row) axis  */
  justifyItems?: "start" | "end" | "center" | "stretch";
  /** Custom class name for setting specific CSS */
  className?: string;
  style?: React.CSSProperties;
}

const Grid = ({ ref, ...props }: GridProps) => {
  const {
    columns = 12,
    gap,
    columnGap,
    rowGap,
    alignContent,
    alignItems,
    justifyContent,
    justifyItems,
    className,
    style,
    ...rest
  } = props;
  const classes = classNames("mobius", "mobius-grid", className);

  const styles: CSSProperties = filterUndefinedProps({
    boxSizing: "border-box",
    display: "grid",
    gridTemplateColumns: `repeat(${columns}, 1fr)`,
    gap: getSpacingValue(gap),
    columnGap: getSpacingValue(columnGap),
    rowGap: getSpacingValue(rowGap),
    alignContent,
    alignItems,
    justifyContent,
    justifyItems,
    ...style,
  });

  return <div ref={ref} style={styles} className={classes} {...rest} />;
};

Grid.displayName = "Grid";
export { Grid };
