import type { JSXElementConstructor } from "react";
import { useCallback } from "react";

export interface UseButtonProps {
  elementType?:
    | "button"
    | "a"
    | "span"
    | "input"
    | JSXElementConstructor<unknown>
    | undefined;
  type?: "button" | "submit" | "reset";
  isDisabled?: boolean;
  onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
  onPress?: (event: React.MouseEvent<HTMLButtonElement>) => void;
  href?: string;
  target?: string;
  rel?: string;
  role?: string;
  name?: string | undefined;
  value?: string | undefined;
}

export function useButton({
  elementType = "button",
  type = "button",
  isDisabled = false,
  href,
  target,
  rel,
  role,
  name,
  value,
  onClick,
  onPress,
}: UseButtonProps) {
  const realOnClick = useCallback(
    (event: React.MouseEvent<HTMLButtonElement>) => {
      if (isDisabled) {
        return;
      }

      onClick?.(event);
      onPress?.(event);
    },
    [isDisabled, onClick, onPress],
  );

  function getRole() {
    if (role) {
      return role;
    }

    if (elementType === "a") {
      return undefined;
    }

    return "button";
  }

  const extraProps =
    elementType === "button"
      ? { type }
      : {
          role: getRole(),
        };

  return {
    buttonProps: {
      href: elementType === "a" ? href : undefined,
      target: elementType === "a" ? target : undefined,
      rel: elementType === "a" ? rel : undefined,
      tabIndex: isDisabled ? -1 : 0,
      disabled: isDisabled || undefined,
      "aria-disabled": isDisabled || undefined,
      name:
        elementType === "input" || elementType === "button" ? name : undefined,
      value:
        elementType === "input" || elementType === "button" ? value : undefined,
      ...extraProps,
      onClick: realOnClick,
    },
  };
}
