import type { SerializedStyles } from "@emotion/react";
import { css } from "@emotion/react";
import type { ReactNode } from "react";
import type { ButtonProps } from "react-aria-components";
import { Button } from "react-aria-components";

import type { ColorValue, TextColorValue } from "../types";
import type { ComponentSize } from "../types/sizing";
import { colorValue } from "../utils";

const getIconButtonColor = (color: TextColorValue): string => {
  if (color === "inherit") {
    return "inherit";
  }
  if (color.startsWith("text-")) {
    const [, num] = color.split("-");
    return `var(--global-text-color-${num})`;
  }
  return colorValue(color as ColorValue);
};

export interface IconButtonProps extends Omit<ButtonProps, "children"> {
  /**
   * The size of the button. `XS` is the inline size — a 20px square for
   * icon buttons nestled inside inputs and other compact rows.
   * @default 'M'
   */
  size?: "XS" | Exclude<ComponentSize, "L">;
  /**
   * The icon to display
   */
  children: ReactNode;
  /**
   * The color of the button and icon
   * @default 'text-700'
   */
  color?: TextColorValue;
  /**
   * Custom CSS styles
   */
  css?: SerializedStyles;
}

const iconButtonCSS = (color: TextColorValue) => css`
  --icon-button-font-size-xs: var(--global-font-size-m);
  --icon-button-font-size-s: var(--global-font-size-l);
  --icon-button-font-size-m: var(--global-font-size-xl);
  --icon-button-font-size-l: var(--global-font-size-2xl);

  display: flex;
  align-items: center;
  justify-content: center;
  border: var(--global-border-size-thin) solid transparent;
  border-radius: var(--global-rounding-small);
  color: ${getIconButtonColor(color)};
  background-color: transparent;
  cursor: pointer;
  transition:
    background-color 0.2s ease,
    color 0.2s ease,
    opacity 0.2s ease;
  position: relative;
  padding: 0;

  /* No button-height token exists this small — XS is the inline size for
     icon buttons living inside inputs */
  &[data-size="XS"] {
    width: var(--global-dimension-size-250);
    min-width: var(--global-dimension-size-250);
    min-height: var(--global-dimension-size-250);
    height: var(--global-dimension-size-250);
    .icon-wrap {
      font-size: var(--icon-button-font-size-xs);
    }
  }

  &[data-size="S"] {
    width: var(--global-button-height-s);
    min-width: var(--global-button-height-s);
    min-height: var(--global-button-height-s);
    height: var(--global-button-height-s);
    .icon-wrap {
      font-size: var(--icon-button-font-size-s);
    }
  }

  &[data-size="M"] {
    width: var(--global-button-height-m);
    min-width: var(--global-button-height-m);
    min-height: var(--global-button-height-m);
    height: var(--global-button-height-m);
    .icon-wrap {
      font-size: var(--icon-button-font-size-m);
    }
  }

  .icon-wrap {
    opacity: 0.7;
    transition: opacity 0.2s ease;
  }

  &[data-hovered] {
    background-color: var(--hover-background);
    .icon-wrap {
      opacity: 1;
    }
  }

  &[data-pressed] {
    background-color: var(--global-color-primary-100);
    color: var(--global-text-color-900);
  }

  &[data-focus-visible] {
    outline: var(--focus-ring-thickness) solid var(--focus-ring-color);
    outline-offset: var(--focus-ring-offset);
  }

  &[data-disabled] {
    opacity: var(--global-opacity-disabled);
    cursor: not-allowed;
  }
`;

export function IconButton({
  size = "M",
  color = "text-700",
  children,
  ...props
}: IconButtonProps) {
  return (
    <Button css={iconButtonCSS(color)} data-size={size} {...props}>
      {children}
    </Button>
  );
}
