import * as React from 'react'
import { Slot } from '@radix-ui/react-slot'
import { cva, type VariantProps } from 'class-variance-authority'
import { cn } from '@/lib/utils'

/**
 * Button — shadcn-стиль, адаптирован под наш token palette.
 *
 * Variants per design handoff:
 *  - primary  — navy bg + on-accent text (deep coffee → cream).
 *  - secondary — surface bg + ink text + line border (default outlined).
 *  - ghost    — transparent + hover:surface-2.
 *  - danger   — pink bg + on-accent text (destructive actions).
 *  - link     — accent text + underline-offset, no bg.
 *
 * Sizes: sm (28px), md (36px default), lg (40px), icon-sm (24px square),
 * icon (32px square).
 *
 * Use {@code asChild} (Radix Slot pattern) для рендера кастомного root
 * элемента — например {@code <Button asChild><Link to="/">…</Link></Button>}.
 */
const buttonVariants = cva(
  [
    'inline-flex items-center justify-center gap-2 whitespace-nowrap',
    'rounded-md text-body font-medium transition-colors',
    'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-bg',
    'disabled:pointer-events-none disabled:opacity-50',
    '[&_svg]:pointer-events-none [&_svg]:shrink-0',
  ].join(' '),
  {
    variants: {
      variant: {
        primary:
          'bg-navy text-on-accent hover:opacity-90 active:opacity-95',
        secondary:
          'border border-line bg-surface text-ink hover:bg-surface-2',
        ghost:
          'text-ink hover:bg-surface-2',
        danger:
          'bg-pink text-on-accent hover:opacity-90 active:opacity-95',
        link:
          'text-accent underline-offset-4 hover:underline',
      },
      size: {
        sm: 'h-7 px-2.5 text-cell',
        md: 'h-9 px-3.5',
        lg: 'h-10 px-4',
        'icon-sm': 'h-6 w-6',
        icon: 'h-8 w-8',
      },
    },
    defaultVariants: {
      variant: 'primary',
      size: 'md',
    },
  },
)

export type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> &
  VariantProps<typeof buttonVariants> & {
    asChild?: boolean
    leftIcon?: React.ReactNode
    rightIcon?: React.ReactNode
    /** Loading state — disables button + replaces leftIcon с inline spinner. */
    loading?: boolean
  }

export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
  function Button(
    {
      className,
      variant,
      size,
      asChild,
      leftIcon,
      rightIcon,
      loading,
      disabled,
      children,
      ...props
    },
    ref,
  ) {
    const Comp = asChild ? Slot : 'button'
    const renderedLeftIcon = loading ? (
      <svg className="animate-spin size-3.5" viewBox="0 0 24 24" aria-hidden>
        <circle cx="12" cy="12" r="10" fill="none" stroke="currentColor" strokeOpacity="0.25" strokeWidth="4" />
        <path d="M4 12a8 8 0 0 1 8-8" fill="none" stroke="currentColor" strokeWidth="4" strokeLinecap="round" />
      </svg>
    ) : (
      leftIcon
    )
    return (
      <Comp
        ref={ref}
        className={cn(buttonVariants({ variant, size }), className)}
        disabled={disabled || loading}
        aria-busy={loading || undefined}
        {...props}
      >
        {renderedLeftIcon}
        {children}
        {rightIcon}
      </Comp>
    )
  },
)

export { buttonVariants }
