import { forwardRef, memo, useCallback, useState } from "react";

import { styled } from "../../theme";
import { pxToRem } from "../../utils";
import { Icons } from "../icons";
import { body4Variant } from "../text";

const ChevronContainer = styled("span", {
  display: "flex",
  borderRadius: "$round",
  alignItems: "center",
  justifyContent: "center",
  flexShrink: 0,
  size: pxToRem(20),
});

const StyledButton = styled("button", {
  display: "flex",
  alignItems: "center",
  justifyContent: "space-between",
  gap: "$2",
  color: "$light-off-white",
  cursor: "pointer",

  ...body4Variant,
  fontWeight: "$bold",

  '&[aria-expanded="true"]': {
    [`& ${ChevronContainer}`]: {
      transform: "rotate(180deg)",
    },
  },

  "&:focus, &:hover": {
    [`& ${ChevronContainer}`]: {
      backgroundColor: "$off-white-9",
    },
  },

  "&:focus": {
    [`& ${ChevronContainer}`]: {
      boxShadow: `inset 0 0 0 ${pxToRem(2)} $off-white-72`,
    },
  },
});

interface Props extends Omit<React.ComponentProps<typeof StyledButton>, "aria-expanded"> {
  /**
   * Text to show when button is collabsed
   */
  collapsedText: string;
  /**
   * Text to show when button is expanded
   */
  expandedText: string;
  /**
   * The controlled expanded state.
   */
  isExpanded?: boolean;
  /**
   * Event handler called when the expanded state changes.
   */
  onExpandedChange?: (isExpanded: boolean) => void;
}

const ShowMoreTextButtonComponent = forwardRef<HTMLButtonElement, Props>((props, ref) => {
  const {
    collapsedText,
    expandedText,
    isExpanded: isExpandedProp,
    onClick,
    onExpandedChange,
    ...rest
  } = props;
  const [isExpandedInternal, setIsExpandedInternal] = useState(false);

  const isExpanded = typeof isExpandedProp === "undefined" ? isExpandedInternal : isExpandedProp;

  const handleOnClick: React.MouseEventHandler<HTMLButtonElement> = useCallback(
    (e) => {
      if (typeof isExpandedProp === "undefined") {
        setIsExpandedInternal(!isExpanded);
      }
      onExpandedChange?.(!isExpanded);
      onClick?.(e);
    },
    [onClick, onExpandedChange, isExpandedProp, isExpanded]
  );

  return (
    <StyledButton {...rest} ref={ref} onClick={handleOnClick} aria-expanded={isExpanded}>
      {isExpanded ? expandedText : collapsedText}

      <ChevronContainer>
        <Icons.ChevronDown size="s" />
      </ChevronContainer>
    </StyledButton>
  );
});

ShowMoreTextButtonComponent.displayName = "ShowMoreTextButton";

/**
 * A reusable component intended to be used to achieve a show more/show less usecase
 */
export const ShowMoreButton = memo(ShowMoreTextButtonComponent);
