import clsx from "clsx";
import * as React from "react";
import { useDebugEvents } from "../../utils";
import { Icon } from "../Icon";
import { ButtonContext, handleEnterPress } from "../Link";
import { TooltipSymbol } from "../Tooltip";
import * as styles from "./legacy.module.css";

export interface LegacyButtonProps {
  "data-id"?: string;
  icon?: React.ReactNode;
  iconSide?: "left" | "right";
  isLoading?: boolean;
  as?: any; // string | React.ReactElement;
  value?: string;
  onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
  className?: string;
}

export const LegacyButton = (
  allProps: LegacyButtonProps & React.ComponentProps<"button">,
) => {
  const {
    as = "button",
    className,
    iconSide,
    value,
    icon,
    disabled,
    isLoading,
    ...rest
  } = allProps;
  const isChild = React.useContext(ButtonContext);
  const Tag = as;
  const { onClick, ...props } = useDebugEvents(rest);
  return (
    <ButtonContext.Provider value={true}>
      {isChild ? (
        <span
          className={clsx(styles.button as any, className)}
          role="button"
          tabIndex={0}
          onKeyDown={handleEnterPress}
          aria-disabled={disabled as boolean}
          onClick={disabled ? undefined : onClick}
          {...props}
        >
          {isLoading ? <ButtonSpinner /> : null}
          {isLoading ? (
            <span style={{ opacity: 0 }}>
              <ButtonContent value={value} icon={icon} iconSide={iconSide} />
            </span>
          ) : (
            <ButtonContent value={value} icon={icon} iconSide={iconSide} />
          )}
        </span>
      ) : (
        <Tag
          className={clsx(styles.button, className)}
          disabled={disabled}
          onClick={onClick}
          {...props}
        >
          {isLoading ? <ButtonSpinner /> : null}
          {isLoading ? (
            <span style={{ opacity: 0 }}>
              <ButtonContent value={value} icon={icon} iconSide={iconSide} />
            </span>
          ) : (
            <ButtonContent value={value} icon={icon} iconSide={iconSide} />
          )}
        </Tag>
      )}
    </ButtonContext.Provider>
  );
};

function ButtonSpinner({
  label,
  children = <Spinner />,
}: {
  label?: string;
  children?: React.ReactNode;
}) {
  return (
    <div
      className={clsx(
        styles.spinnerContainer,
        label && styles.spinnerContainerLabel,
      )}
    >
      {children}
    </div>
  );
}

interface SpinnerProps extends React.HTMLAttributes<HTMLDivElement> {
  label?: string;
}

function Spinner({ label, className }: SpinnerProps) {
  return (
    <div role="status" className={clsx(styles.spinner, className)}>
      {label && <div className="sr-only">{label}</div>}
    </div>
  );
}

function ButtonIcon(props: React.ComponentProps<"span">) {
  const { children, className, ...rest } = props;

  const _children = React.isValidElement(children)
    ? React.cloneElement(children, {
        "aria-hidden": true,
        focusable: false,
      } as React.HTMLAttributes<HTMLSpanElement>)
    : children;

  return (
    <span className={clsx(styles.icon, className)} {...rest}>
      {_children}
    </span>
  );
}

function ButtonContent(
  props: Pick<LegacyButtonProps, "icon" | "iconSide" | "value">,
) {
  const { icon, iconSide = "left", value } = props;
  return (
    <>
      {icon && iconSide === "left" && (
        <ButtonIcon>
          <Icon>{icon}</Icon>
        </ButtonIcon>
      )}
      {value ? (
        <span className={clsx("__button-content", styles.buttonContent)}>
          {value}
        </span>
      ) : null}
      {icon && iconSide === "right" && (
        <ButtonIcon>
          <Icon>{icon}</Icon>
        </ButtonIcon>
      )}
    </>
  );
}

LegacyButton[TooltipSymbol] = true;
