"use client";

import type { RefAttributes, CSSProperties } from "react";
import { useEffect, useState } from "react";
import classNames from "classnames/dedupe";
import type { DOMProps } from "../../types/dom";
import { useBreakpoint } from "../../hooks";
import type { SizeType } from "../../types";

export type GridItemElementType = HTMLDivElement;

export interface GridItemProps
  extends RefAttributes<GridItemElementType>, DOMProps {
  /** How many columns the item spans */
  span?: number | number[];
  /** React children */
  children?: React.ReactNode;
  /** How many columns the item spans on the smallest breakpoint */
  xs?: number;
  sm?: number;
  md?: number;
  lg?: number;
  xl?: number;
  /** How many columns the item spans on the largest breakpoint */
  xxl?: number;
  /** Aligns the grid item along the block (column) axis */
  alignSelf?: "center" | "start" | "end" | "stretch";
  /** Aligns the grid item along the inline (row) axis */
  justifySelf?: "center" | "start" | "end" | "stretch";
  /** Custom class name for setting specific CSS */
  className?: string;
}

export const getBreakpointMap = (config: Partial<Record<SizeType, number>>) =>
  Object.entries(config).reduce<Record<string, number | undefined>>(
    (prev, [key, value]) => {
      const previous = Object.values(prev);
      const lastDefined = previous[previous.length - 1];
      return { ...prev, [key]: value || lastDefined };
    },
    {},
  );

export const DEFAULT_SPAN = 12;

const GridItem = ({ ref, ...props }: GridItemProps) => {
  const {
    breakpoint: { size: breakpointSize },
  } = useBreakpoint();
  const {
    span,
    xs = Array.isArray(span) ? DEFAULT_SPAN : span,
    sm,
    md,
    lg,
    xl,
    xxl,
    alignSelf,
    justifySelf,
    className,
    ...rest
  } = props;
  const breakpointMap = getBreakpointMap({
    xs,
    sm,
    md,
    lg,
    xl,
    xxl,
  });
  const [responsiveSpan, setResponsiveSpan] = useState<number | undefined>();
  const classes = classNames("mobius", "mobius-grid__item", className);

  useEffect(() => {
    setResponsiveSpan(breakpointMap[breakpointSize]);
  }, [breakpointSize, breakpointMap]);

  const styles: CSSProperties = {
    gridColumn: responsiveSpan ? `span ${responsiveSpan}` : undefined,
    alignSelf,
    justifySelf,
  };

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

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