import { cva, type VariantProps } from 'class-variance-authority'
import type { ReactNode, ElementType, ComponentPropsWithoutRef } from 'react'
import { twMerge } from 'tailwind-merge'

const buttonVariants = cva(
  'inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
  {
    variants: {
      variant: {
        newsPrimary: 'bg-[#2E2F7C] text-white text-lg',
        newsPrimaryOutline: 'border-[3px] border-white text-white text-lg',
        newsSecondary: 'border-[3px] border-[#2E2F7C] text-[#2E2F7C] text-lg',
        icon: '',
        link: '',
      },
      size: {
        default: 'h-[50px] w-[150px]',
        block: 'h-[50px] w-full',
        icon: 'h-9 w-9',
        sm: 'h-8 rounded-md px-3 text-xs',
        lg: 'h-10 rounded-md px-8',
        fit: 'w-fit',
      },
    },
    defaultVariants: {
      variant: 'newsPrimary',
      size: 'default',
    },
  },
)

type ButtonBaseProperties = {
  children: ReactNode
  variant?: VariantProps<typeof buttonVariants>['variant']
  size?: VariantProps<typeof buttonVariants>['size']
  className?: string
}

type PolymorphicReference<C extends ElementType> =
  ComponentPropsWithoutRef<C>['ref']

type ButtonProperties<C extends ElementType> = ButtonBaseProperties & {
  as?: C
  ref?: PolymorphicReference<C>
} & Omit<ComponentPropsWithoutRef<C>, keyof ButtonBaseProperties>

export const Button = <C extends ElementType = 'button'>({
  as,
  children,
  variant,
  size,
  className,
  ...properties
}: ButtonProperties<C>) => {
  const Component = as || 'button'
  const classes = twMerge(buttonVariants({ variant, size, className }))

  return (
    <Component
      className={classes}
      {...properties}
    >
      {children}
    </Component>
  )
}
