import * as React from "react";
import { Loader2 } from "@/components/ui/icons";
import { cn } from "@/lib/utils";

type Variant = "primary" | "secondary" | "ghost" | "outline" | "danger";
type Size = "sm" | "md" | "lg";

type Props = React.ButtonHTMLAttributes<HTMLButtonElement> & {
  variant?: Variant;
  size?: Size;
  loading?: boolean;
};

// Transitions ciblees (pas `all`) + easing custom emil-design : 160ms cubic-bezier
// (0.23, 1, 0.32, 1). Active scale 0.97 (vs 0.98) plus perceptible sans creer
// de jitter au cursor (le `translate-y` du hover a ete retire).
const base =
  "relative inline-flex items-center justify-center gap-2 rounded-md font-medium cursor-pointer transition-[transform,background-color,box-shadow,border-color,color] duration-150 ease-[cubic-bezier(0.23,1,0.32,1)] active:scale-[0.97] disabled:pointer-events-none disabled:opacity-50 disabled:cursor-not-allowed whitespace-nowrap focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/55 focus-visible:ring-offset-2 focus-visible:ring-offset-background";

const variantClasses: Record<Variant, string> = {
  primary:
    "bg-accent text-accent-fg shadow-[var(--shadow-accent-soft)] hover:bg-accent-hi hover:shadow-[var(--shadow-accent-hi)]",
  secondary: "bg-surface-2 text-text border border-border hover:bg-surface-3 hover:border-border-strong",
  ghost: "text-text-muted hover:text-text hover:bg-stone-900/[0.08] hover:ring-1 hover:ring-border",
  outline: "border border-border text-text hover:border-accent/45 hover:text-accent hover:bg-accent/[0.06]",
  danger: "bg-danger/10 text-danger border border-danger/30 hover:bg-danger/20 hover:border-danger/50",
};

// Mobile-first touch targets : sous md, on garantit ≥ 44 px (WCAG).
// Au-dessus de md, on libère selon variant.
const sizeClasses: Record<Size, string> = {
  sm: "min-h-11 md:min-h-8 h-11 md:h-8 px-3 text-xs",
  md: "min-h-11 md:min-h-10 h-11 md:h-10 px-4 text-sm",
  lg: "min-h-11 h-11 px-5 text-sm",
};

export const Button = React.forwardRef<HTMLButtonElement, Props>(
  ({ variant = "primary", size = "md", className, loading, disabled, children, ...props }, ref) => {
    const isDisabled = disabled || loading;
    return (
      <button
        ref={ref}
        disabled={isDisabled}
        aria-busy={loading || undefined}
        className={cn(base, variantClasses[variant], sizeClasses[size], className)}
        {...props}
      >
        {loading && (
          <span className="absolute inset-0 flex items-center justify-center">
            <Loader2 className="size-4 animate-spin" />
          </span>
        )}
        <span className={cn("inline-flex items-center gap-2", loading && "invisible")}>{children}</span>
      </button>
    );
  },
);
Button.displayName = "Button";
