"use client";

import type { MouseEvent, ReactNode, RefAttributes } from "react";
import classNames from "classnames/dedupe";
import type { DOMProps } from "../../types/dom";
import { Loading } from "./Loading";
import type { UseButtonProps } from "../../hooks/useButton";
import { useButton } from "../../hooks/useButton";
import { Success } from "./Success";
import "./Button.css";

export type ButtonElementType = HTMLButtonElement;

export type Variant = "primary" | "secondary" | "ghost" | "basic" | "link";

export type Size = "sm" | "md" | "lg";

export interface ButtonProps
  extends UseButtonProps, DOMProps, RefAttributes<ButtonElementType> {
  /** The name of the button when submitted in a form */
  name?: string | undefined;
  /** The value of the button when submitted in a form */
  value?: string | undefined;
  /** Custom class name for setting specific CSS */
  className?: string;
  /** Shortlist of styles */
  variant?: Variant;
  size?: Size;
  /** Display loading spinner */
  isLoading?: boolean;
  /** Display success style */
  isSuccess?: boolean;
  onClick?: (event: MouseEvent<HTMLButtonElement>) => void;
  children?: ReactNode;
}

const Button = ({ ref, ...props }: ButtonProps) => {
  const {
    children,
    elementType: Component = "button" as React.ElementType,
    isDisabled,
    isLoading,
    isSuccess,
    variant = "primary",
    size = "md",

    onPress,

    onClick,
    ...otherProps
  } = props;
  const { buttonProps } = useButton(props);

  // Reshape class name and apply to outer element
  otherProps.className = classNames(
    "mobius",
    "mobius-button",
    `--variant-${variant}`,
    `--size-${size}`,
    {
      "--is-disabled": isDisabled,
      "--is-loading": isLoading,
      "--is-success": isSuccess && !isLoading,
    },
    otherProps.className,
  );

  return (
    <Component ref={ref} {...buttonProps} {...otherProps}>
      {isLoading ? <Loading>{children}</Loading> : children}
      {isSuccess && !isLoading && <Success />}
    </Component>
  );
};

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