import { type ButtonHTMLAttributes, forwardRef } from 'react'
import { Loader2 } from 'lucide-react'

/**
 * Button component variants
 * - primary: Main action button using design system primary color (Blue-600)
 * - secondary: Secondary action button with subtle background
 * - outline: Bordered button with transparent background
 * - danger: Destructive action button using design system error color (Red-500)
 * - ghost: Minimal button with no background, only hover state
 */
export type ButtonVariant = 'primary' | 'secondary' | 'outline' | 'danger' | 'ghost'

/**
 * Button component sizes
 * - sm: Small button for compact UIs
 * - md: Medium button (default)
 * - lg: Large button for prominent actions
 */
export type ButtonSize = 'sm' | 'md' | 'lg'

export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
  /** Visual style variant of the button */
  variant?: ButtonVariant
  /** Size of the button */
  size?: ButtonSize
  /** Shows a loading spinner and disables the button */
  loading?: boolean
  /** Optional icon to display before the button text */
  icon?: React.ReactNode
}

/**
 * A reusable Button component with support for multiple variants, sizes,
 * loading state, and disabled state. Uses TailwindCSS with design system colors.
 *
 * @example
 * // Primary button
 * <Button variant="primary">Submit</Button>
 *
 * @example
 * // Loading state
 * <Button loading>Processing...</Button>
 *
 * @example
 * // With icon
 * <Button icon={<PlusIcon />}>Add Item</Button>
 */
const Button = forwardRef<HTMLButtonElement, ButtonProps>(
  (
    {
      className = '',
      variant = 'primary',
      size = 'md',
      loading = false,
      disabled,
      icon,
      children,
      ...props
    },
    ref
  ) => {
    // Base styles applied to all button variants
    const baseStyles = [
      'inline-flex items-center justify-center',
      'font-medium rounded-lg',
      'transition-colors duration-200',
      'focus:outline-none focus:ring-2 focus:ring-offset-2',
      'disabled:opacity-50 disabled:cursor-not-allowed',
    ].join(' ')

    // Variant-specific styles using design system colors
    const variantStyles: Record<ButtonVariant, string> = {
      // Primary: Blue-600 (#2563EB) - Main action button
      primary: [
        'bg-primary-600 text-white',
        'hover:bg-primary-700',
        'focus:ring-primary-500',
        'dark:bg-primary-500 dark:hover:bg-primary-600',
      ].join(' '),

      // Secondary: Slate background - Secondary action button
      secondary: [
        'bg-slate-100 text-slate-900',
        'hover:bg-slate-200',
        'focus:ring-slate-500',
        'dark:bg-slate-700 dark:text-slate-100 dark:hover:bg-slate-600',
      ].join(' '),

      // Outline: Bordered button with transparent background
      outline: [
        'border border-slate-300 text-slate-700 bg-transparent',
        'hover:bg-slate-50',
        'focus:ring-slate-500',
        'dark:border-slate-600 dark:text-slate-300 dark:hover:bg-slate-800',
      ].join(' '),

      // Danger: Red-500 (#EF4444) - Destructive action button
      danger: [
        'bg-error-500 text-white',
        'hover:bg-error-600',
        'focus:ring-error-500',
        'dark:bg-error-500 dark:hover:bg-error-600',
      ].join(' '),

      // Ghost: Transparent background - Minimal button
      ghost: [
        'text-slate-700 bg-transparent',
        'hover:bg-slate-100',
        'focus:ring-slate-500',
        'dark:text-slate-300 dark:hover:bg-slate-800',
      ].join(' '),
    }

    // Size-specific styles
    const sizeStyles: Record<ButtonSize, string> = {
      sm: 'px-3 py-1.5 text-sm gap-1.5',
      md: 'px-4 py-2 text-sm gap-2',
      lg: 'px-6 py-3 text-base gap-2',
    }

    // Spinner size based on button size
    const spinnerSizeStyles: Record<ButtonSize, string> = {
      sm: 'h-3.5 w-3.5',
      md: 'h-4 w-4',
      lg: 'h-5 w-5',
    }

    const isDisabled = disabled || loading

    return (
      <button
        ref={ref}
        className={`${baseStyles} ${variantStyles[variant]} ${sizeStyles[size]} ${className}`}
        disabled={isDisabled}
        aria-busy={loading}
        aria-disabled={isDisabled}
        {...props}
      >
        {loading ? (
          <Loader2
            className={`${spinnerSizeStyles[size]} animate-spin`}
            aria-hidden="true"
          />
        ) : icon ? (
          <span className="flex-shrink-0" aria-hidden="true">
            {icon}
          </span>
        ) : null}
        {children}
      </button>
    )
  }
)

Button.displayName = 'Button'

export default Button
