/**
 * Button Component
 *
 * 🔒 STYLE LOCKED - See DESIGN_SYSTEM.md for available variants and sizes.
 * Do not modify variants or add new ones without updating DESIGN_SYSTEM.md first.
 */
import { ReactNode, forwardRef } from "react";
import clsx from "clsx";
import { twMerge } from "tailwind-merge";

type ButtonSize = "xs" | "sm" | "md" | "lg" | "xl" | "2xl";
type ButtonVariant = "primary" | "secondary" | "outline" | "ghost" | "gradient";
type ButtonTone = "brand" | "success" | "warning" | "danger" | "neutral";
type ButtonShape = "rounded" | "pill";
type ButtonElement = HTMLButtonElement;

interface ButtonProps {
  children: ReactNode; // Button text or content
  size?: ButtonSize; // Button size
  variant?: ButtonVariant; // Visual variant
  tone?: ButtonTone; // Color tone
  shape?: ButtonShape; // Border radius style
  startIcon?: ReactNode; // Icon before the text
  endIcon?: ReactNode; // Icon after the text
  onClick?: () => void; // Click handler
  disabled?: boolean; // Disabled state
  fullWidth?: boolean; // Stretch to parent width
  className?: string; // Additional classes
  type?: "button" | "submit" | "reset"; // Button type
}

const toneMap: Record<
  ButtonTone,
  {
    primary: string;
    secondary: string;
    outline: string;
    ghost: string;
    ring: string;
  }
> = {
  brand: {
    primary: "bg-brand-500 text-white hover:bg-brand-600",
    secondary:
      "bg-gray-500 text-white hover:bg-gray-600 dark:bg-gray-500 dark:hover:bg-gray-600",
    outline:
      "text-brand-600 ring-1 ring-brand-200 hover:bg-brand-25 dark:ring-brand-500/40 dark:text-brand-300 dark:hover:bg-brand-500/[0.08]",
    ghost:
      "text-brand-600 hover:bg-brand-50 dark:text-brand-300 dark:hover:bg-brand-500/[0.08]",
    ring: "focus-visible:ring-brand-500",
  },
  success: {
    primary: "bg-success-500 text-white hover:bg-success-600",
    secondary:
      "bg-gray-500 text-white hover:bg-gray-600 dark:bg-gray-500 dark:hover:bg-gray-600",
    outline:
      "text-success-600 ring-1 ring-success-200 hover:bg-success-25 dark:ring-success-500/40 dark:text-success-300",
    ghost:
      "text-success-600 hover:bg-success-50 dark:text-success-300 dark:hover:bg-success-500/[0.08]",
    ring: "focus-visible:ring-success-500",
  },
  warning: {
    primary: "bg-warning-500 text-white hover:bg-warning-600",
    secondary:
      "bg-gray-500 text-white hover:bg-gray-600 dark:bg-gray-500 dark:hover:bg-gray-600",
    outline:
      "text-warning-600 ring-1 ring-warning-200 hover:bg-warning-25 dark:ring-warning-500/40 dark:text-warning-300",
    ghost:
      "text-warning-600 hover:bg-warning-50 dark:text-warning-300 dark:hover:bg-warning-500/[0.08]",
    ring: "focus-visible:ring-warning-500",
  },
  danger: {
    primary: "bg-error-500 text-white hover:bg-error-600",
    secondary:
      "bg-gray-500 text-white hover:bg-gray-600 dark:bg-gray-500 dark:hover:bg-gray-600",
    outline:
      "text-error-600 ring-1 ring-error-200 hover:bg-error-25 dark:ring-error-500/40 dark:text-error-300",
    ghost:
      "text-error-600 hover:bg-error-50 dark:text-error-300 dark:hover:bg-error-500/[0.08]",
    ring: "focus-visible:ring-error-500",
  },
  neutral: {
    primary:
      "bg-gray-900 text-white hover:bg-gray-800 dark:bg-white/10 dark:hover:bg-white/20",
    secondary:
      "bg-gray-500 text-white hover:bg-gray-600 dark:bg-gray-500 dark:hover:bg-gray-600",
    outline:
      "text-gray-700 ring-1 ring-gray-300 hover:bg-gray-50 dark:text-gray-200 dark:ring-white/[0.08] dark:hover:bg-white/[0.04]",
    ghost:
      "text-gray-700 hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-white/[0.04]",
    ring: "focus-visible:ring-gray-400",
  },
};

const gradientTone: Record<ButtonTone, string> = {
  brand:
    "text-white shadow-[0_20px_45px_-30px_rgba(6,147,227,0.9)] bg-[linear-gradient(135deg,var(--color-primary)_0%,var(--color-primary-dark)_100%)]",
  success:
    "text-white shadow-[0_20px_45px_-30px_rgba(11,191,135,0.9)] bg-[linear-gradient(135deg,var(--color-success)_0%,var(--color-success-dark)_100%)]",
  warning:
    "text-white shadow-[0_20px_45px_-30px_rgba(255,122,0,0.9)] bg-[linear-gradient(135deg,var(--color-warning)_0%,var(--color-warning-dark)_100%)]",
  danger:
    "text-white shadow-[0_20px_45px_-30px_rgba(239,68,68,0.9)] bg-[linear-gradient(135deg,var(--color-danger)_0%,var(--color-danger-dark)_100%)]",
  neutral:
    "text-white shadow-theme-lg bg-[linear-gradient(135deg,var(--color-gray-900),var(--color-gray-800))]",
};

const sizeClasses: Record<ButtonSize, string> = {
  xs: "h-7 px-2.5 text-xs",
  sm: "h-9 px-3 text-sm",
  md: "h-10 px-4 text-sm",
  lg: "h-12 px-5 text-base",
  xl: "h-14 px-6 text-lg",
  "2xl": "h-auto px-8 py-4 text-lg font-semibold",
};

const Button = forwardRef<ButtonElement, ButtonProps>(
  (
    {
      children,
      size = "md",
      variant = "primary",
      tone = "brand",
      shape = "rounded",
      startIcon,
      endIcon,
      onClick,
      className = "",
      disabled = false,
      fullWidth = false,
      type = "button",
    },
    ref,
  ) => {
    const toneStyles = toneMap[tone];

    const variantClasses: Record<ButtonVariant, string> = {
      primary: toneStyles.primary,
      secondary: toneStyles.secondary,
      outline: clsx(
        "bg-transparent transition-colors",
        toneStyles.outline,
        "dark:bg-transparent",
      ),
      ghost: toneStyles.ghost,
      gradient: gradientTone[tone],
    };

    const baseClasses =
      "inline-flex items-center justify-center gap-2 font-medium transition duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed";

    const shapeClasses =
      shape === "pill" ? "rounded-full" : "rounded-lg";

    const ringClass = variant === "gradient" ? "focus-visible:ring-white/70" : toneStyles.ring;

    const computedClass = twMerge(
      clsx(
        baseClasses,
        sizeClasses[size],
        shapeClasses,
        variantClasses[variant],
        ringClass,
        {
          "w-full": fullWidth,
        },
        className,
      ),
    );

    return (
      <button
        ref={ref}
        className={computedClass}
        onClick={onClick}
        type={type}
        disabled={disabled}
      >
        {startIcon && <span className="flex items-center">{startIcon}</span>}
        <span className="whitespace-nowrap">{children}</span>
        {endIcon && <span className="flex items-center">{endIcon}</span>}
      </button>
    );
  },
);

Button.displayName = "Button";

export default Button;
