'use client'

import { forwardRef, type ButtonHTMLAttributes, type ReactNode } from 'react'
import { cv, type VariantProps } from '../../lib/cv.js'

const button = cv(
  // Base classes apply to every variant.
  'focus-visible:ring-offset-background inline-flex items-center justify-center gap-2 rounded-[var(--radius)] font-medium transition-colors focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2 focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50',
  {
    variants: {
      variant: {
        primary: 'bg-[var(--primary)] text-[var(--primary-foreground)] hover:opacity-90',
        secondary: 'bg-[var(--secondary)] text-[var(--secondary-foreground)] hover:opacity-80',
        danger: 'bg-[var(--destructive)] text-[var(--destructive-foreground)] hover:opacity-90',
        ghost: 'bg-transparent text-[var(--foreground)] hover:bg-[var(--accent)]',
        outline:
          'border border-[var(--border)] bg-transparent text-[var(--foreground)] hover:bg-[var(--accent)]',
        link: 'bg-transparent text-[var(--primary)] underline-offset-4 hover:underline',
      },
      size: {
        xs: 'h-7 px-2 text-xs',
        sm: 'h-8 px-2.5 text-xs',
        md: 'h-9 px-4 text-sm',
        lg: 'h-10 px-6 text-base',
        icon: 'h-9 w-9 p-0',
      },
    },
    defaultVariants: {
      variant: 'primary',
      size: 'md',
    },
  },
)

export type ButtonVariants = VariantProps<typeof button>

export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement>, ButtonVariants {
  loading?: boolean
  /** Stretch the button to fill its container width. */
  full?: boolean
  /** Icon rendered before the children. Use with `size="icon"` for icon-only buttons. */
  leftIcon?: ReactNode
  /** Icon rendered after the children. */
  rightIcon?: ReactNode
  children?: ReactNode
}

export const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button(
  {
    variant,
    size,
    full,
    loading = false,
    disabled,
    leftIcon,
    rightIcon,
    children,
    className,
    ...rest
  },
  ref,
) {
  return (
    <button
      ref={ref}
      disabled={disabled || loading}
      aria-busy={loading || undefined}
      className={button({
        variant,
        size,
        class: [full ? 'w-full' : '', className].filter(Boolean).join(' '),
      })}
      {...rest}
    >
      {loading ? (
        <svg className="h-4 w-4 animate-spin" viewBox="0 0 24 24" fill="none" aria-hidden>
          <circle
            className="opacity-25"
            cx="12"
            cy="12"
            r="10"
            stroke="currentColor"
            strokeWidth="4"
          />
          <path
            className="opacity-75"
            fill="currentColor"
            d="M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z"
          />
        </svg>
      ) : (
        leftIcon
      )}
      {children}
      {!loading && rightIcon}
    </button>
  )
})

export { button as buttonVariants }
