/** Button — the primary action control of the design system (LD). */

import { forwardRef } from "react";

import { cn } from "../lib/cn";
import { Spinner } from "./Spinner";

export type ButtonVariant = "primary" | "secondary" | "ghost" | "danger";
export type ButtonSize = "sm" | "md";

export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
  /** Visual emphasis. Defaults to `secondary`. */
  variant?: ButtonVariant;
  /** Control height. Defaults to `md`. */
  size?: ButtonSize;
  /** When true, shows a spinner and disables the button. */
  loading?: boolean;
}

const BASE =
  "inline-flex items-center justify-center gap-1.5 rounded-md font-medium " +
  "transition-colors select-none disabled:opacity-50 disabled:cursor-not-allowed " +
  "focus-visible:outline-none";

const SIZES: Record<ButtonSize, string> = {
  sm: "h-7 px-2.5 text-xs",
  md: "h-9 px-3.5 text-sm",
};

const VARIANTS: Record<ButtonVariant, string> = {
  primary: "bg-primary text-on-primary hover:bg-primary-hover",
  secondary: "bg-raised text-content border border-border hover:border-border-strong",
  ghost: "text-muted hover:text-content hover:bg-raised",
  danger: "bg-danger text-white hover:brightness-110",
};

/** A themeable button with variants, sizes and a loading state. */
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button(
  { variant = "secondary", size = "md", loading = false, disabled, className, children, ...rest },
  ref,
) {
  return (
    <button
      ref={ref}
      type={rest.type ?? "button"}
      disabled={disabled || loading}
      className={cn(BASE, SIZES[size], VARIANTS[variant], className)}
      {...rest}
    >
      {loading && <Spinner size={size === "sm" ? 12 : 14} />}
      {children}
    </button>
  );
});
