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

import { cn } from '@/lib/utils';
import { useTranslation } from 'react-i18next';
import Case from '../common/case';
import LoaderIcon from '../icons/loader-icon';

const buttonVariants = cva(
  "cursor-pointer inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-xl font-medium transition-[color,box-shadow] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition duration-300 ease-in-out",
  {
    variants: {
      variant: {
        default: 'bg-primary-light text-white hover:bg-primary/90',
        primary: 'bg-primary text-white hover:bg-primary/90',
        subtle: 'bg-primary-subtle text-white hover:bg-primary-subtle/90',
        warning:
          'bg-warning text-white hover:bg-warning/90 focus-visible:ring-warning/20 dark:focus-visible:ring-warning/40',
        destructive:
          'bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40',
        destructiveSubtle:
          'bg-destructive-subtle text-destructive hover:bg-destructive-subtle/90 focus-visible:ring-destructive-subtle/20 dark:focus-visible:ring-destructive-subtle/40',
        outline: 'border border-input bg-transparent',
        outlineSuccess:
          'border border-success border-dashed text-success bg-transparent',
        outlineWarning:
          'border border-warning border-dashed text-warning bg-transparent',
        outlineDestructive:
          'border border-destructive border-dashed text-destructive bg-transparent',
        secondary:
          'bg-black/10 dark:bg-white/10 text-secondary-foreground hover:bg-black/20 dark:hover:bg-white/20 [&>span]:transition-transform [&>span]:duration-300 [&>span]:ease-out hover:[&>span]:translate-x-1 [&>svg]:transition-transform [&>svg]:duration-300 [&>svg]:ease-out hover:[&>svg]:-translate-x-1',
        ai: 'ai-gradient group text-secondary-foreground backdrop-blur-md transition-all duration-300',
        aiBorder:
          'ai-glass-btn group rounded-full px-6 py-2 text-white transition-all duration-300 hover:brightness-110',
        icon: 'bg-transparent hover:bg-accent w-10',
        ghost: 'font-semibold hover:opacity-70',
        ghostPrimary: 'font-semibold text-primary hover:opacity-70',
        ghostDestructive: 'font-semibold text-destructive hover:opacity-70',
        toggle: 'hover:bg-transparent hover:text-accent-foreground',
        link: 'text-primary underline-offset-4 hover:underline',
        accent:
          'bg-accent text-primary hover:bg-accent/90 focus-visible:ring-accent/20 dark:focus-visible:ring-accent/40',
        muted: 'bg-muted text-muted-foreground',
        success:
          'bg-success text-white hover:bg-success/90 focus-visible:ring-success/20 dark:focus-visible:ring-success/40',
        successSubtle:
          'bg-success-subtle text-success hover:bg-success-subtle/90 focus-visible:ring-success-subtle/20 dark:focus-visible:ring-success-subtle/40',
      },
      size: {
        default: 'h-10 px-4 text-base py-2 has-[>svg]:px-3',
        sm: 'h-8 px-3 text-sm has-[>svg]:px-2.5',
        lg: 'h-12 px-6 text-base has-[>svg]:px-4',
        icon: 'size-10',
      },
    },
    defaultVariants: {
      variant: 'default',
      size: 'default',
    },
  },
);

function ButtonComp({
  className,
  variant,
  size,
  asChild = false,
  ...props
}: React.ComponentProps<'button'> &
  VariantProps<typeof buttonVariants> & {
    asChild?: boolean;
  }) {
  const Comp = asChild ? Slot : 'button';

  return (
    <Comp
      data-slot="button"
      className={cn(buttonVariants({ variant, size }), className)}
      {...props}
    />
  );
}

function Button({
  children,
  loading = false,
  className,
  variant,
  size,
  asChild = false,
  ...props
}: React.ComponentProps<'button'> &
  VariantProps<typeof buttonVariants> & {
    asChild?: boolean;
    loading?: boolean;
  }) {
  const { t } = useTranslation();

  return (
    <ButtonComp
      variant={variant}
      size={size}
      className={className}
      asChild={asChild}
      disabled={loading || props.disabled}
      {...props}
    >
      {asChild ? (
        // Slot (asChild) requires a single child element, so pass it straight
        // through without the loading/Case split.
        children
      ) : (
        <>
          <Case condition={loading}>
            <LoaderIcon />
            {t('Loading...')}
          </Case>
          <Case condition={!loading}>{children}</Case>
        </>
      )}
    </ButtonComp>
  );
}

export { Button, buttonVariants };
