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';

const buttonVariants = cva(
    'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-hidden 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',
    {
        defaultVariants: {
            size: 'default',
            variant: 'default',
        },
        variants: {
            size: {
                default: 'h-9 px-4 py-2',
                icon: 'h-9 w-9',
                'icon-lg': 'size-10',
                'icon-sm': 'size-8',
                'icon-xs': 'size-7',
                lg: 'h-10 rounded-md px-8',
                sm: 'h-8 rounded-md px-3 text-xs',
                xs: 'h-7 rounded-md px-2 text-xs gap-1.5',
            },
            variant: {
                default: 'bg-primary text-primary-foreground shadow-sm hover:bg-primary/90',
                destructive: 'bg-destructive text-destructive-foreground shadow-xs hover:bg-destructive/90',
                ghost: 'hover:bg-accent hover:text-accent-foreground',
                link: 'text-primary underline-offset-4 hover:underline',
                outline: 'border border-input bg-background shadow-xs hover:bg-accent hover:text-accent-foreground',
                secondary: 'bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80',
            },
        },
    },
);

export interface ButtonProps extends React.ComponentProps<'button'>, VariantProps<typeof buttonVariants> {
    asChild?: boolean;
}

function Button({ asChild = false, className, size, type, variant, ...props }: ButtonProps) {
    const Comp = asChild ? Slot : 'button';

    return (
        <Comp
            className={cn(buttonVariants({ className, size, variant }))}
            // HTML's default `type` for a `<button>` inside a `<form>` is `submit`,
            // which silently submits the form on every click — every nav cluster,
            // toggle, or dropdown trigger placed inside a form would post the
            // form. The library convention (cf. `InputGroupButton`) is to default
            // to `"button"` and require explicit `type="submit"` for the rare
            // genuine submit buttons. `asChild` consumers control their own
            // element, so we only set the default when we render a real button.
            type={asChild ? type : (type ?? 'button')}
            {...props}
        />
    );
}

export { Button, buttonVariants };
