import * as React from 'react';

import { Slot } from '@radix-ui/react-slot';

import { cn } from '@/lib/utils';

type ButtonVariant = 'default' | 'outline' | 'ghost' | 'link';
type ButtonSize = 'sm' | 'md' | 'lg' | 'icon';
type ButtonLinePosition = 'start' | 'end';

const baseClasses =
  'inline-flex items-center justify-center gap-2 whitespace-nowrap text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-mma-blue focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0';

const sizeClasses: Record<ButtonSize, string> = {
  sm: 'h-8 px-3 text-xs font-normal uppercase tracking-[0.3em] [&_svg]:size-3.5',
  md: 'h-9 px-4 py-2 text-sm [&_svg]:size-4',
  lg: 'h-11 px-6 text-sm font-normal uppercase tracking-[0.3em] [&_svg]:size-5',
  icon: 'h-10 w-10 p-0 [&_svg]:size-5',
};

const variantClasses: Record<ButtonVariant, string> = {
  default: 'shadow bg-mma-blue text-white hover:bg-mma-blue/90',
  outline:
    'border bg-transparent shadow-sm border-[#151720]/35 text-[#151720]/85 hover:bg-[#151720] hover:text-white',
  ghost: 'bg-transparent text-[#151720]/85 hover:bg-[#151720]/10 hover:text-[#151720]',
  link: 'h-auto bg-transparent p-0 text-[#151720] underline-offset-4 hover:underline',
};

const invertedVariantClasses: Record<ButtonVariant, string> = {
  default: 'shadow bg-white text-[#151720] hover:bg-white/90',
  outline: 'border bg-transparent shadow-sm border-white/40 text-white hover:bg-white/10',
  ghost: 'bg-transparent text-white/85 hover:bg-white/10 hover:text-white',
  link: 'h-auto bg-transparent p-0 text-white underline-offset-4 hover:underline',
};

const lineClasses: Record<ButtonLinePosition, string> = {
  end: "after:content-[''] after:block after:h-px after:w-6 after:shrink-0 after:bg-current after:opacity-60",
  start:
    "before:content-[''] before:block before:h-px before:w-6 before:shrink-0 before:bg-current before:opacity-60",
};

type ButtonVariantInput = {
  variant?: ButtonVariant;
  size?: ButtonSize;
  inverted?: boolean;
  line?: boolean;
  linePosition?: ButtonLinePosition;
  className?: string;
};

const buttonVariants = ({
  variant = 'default',
  size = 'md',
  inverted = false,
  line = false,
  linePosition = 'end',
  className,
}: ButtonVariantInput = {}) =>
  cn(
    baseClasses,
    sizeClasses[size],
    inverted ? invertedVariantClasses[variant] : variantClasses[variant],
    line && lineClasses[linePosition],
    className
  );

export interface ButtonProps
  extends React.ButtonHTMLAttributes<HTMLButtonElement>, Omit<ButtonVariantInput, 'className'> {
  asChild?: boolean;
}

const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
  ({ className, variant, size, inverted, line, linePosition, asChild = false, ...props }, ref) => {
    const Comp = asChild ? Slot : 'button';
    return (
      <Comp
        className={cn(buttonVariants({ variant, size, inverted, line, linePosition, className }))}
        ref={ref}
        {...props}
      />
    );
  }
);
Button.displayName = 'Button';

export { Button, buttonVariants };
