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"

const buttonVariants = cva(
  "group/button inline-flex min-w-0 items-center justify-center whitespace-nowrap rounded-[var(--bh-control-default)] text-[length:var(--bh-text-button-font-size)] font-[var(--bh-text-button-font-weight)] leading-[var(--bh-text-button-line-height)] tracking-[var(--bh-text-button-letter-spacing)] outline-none transition-[background-color,border-color,color,box-shadow] focus-visible:shadow-[var(--shadow-button-focus)] disabled:pointer-events-none disabled:shadow-none aria-invalid:border aria-invalid:border-destructive aria-invalid:shadow-[var(--shadow-button-danger-focus)] [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-[var(--bh-button-icon-size)] [&_svg[data-icon='inline-start']]:ms-[var(--bh-button-icon-offset)] [&_svg[data-icon='inline-end']]:me-[var(--bh-button-icon-offset)] rtl:[&_svg[data-rtl-flip='true']]:-scale-x-100",
  {
    variants: {
      variant: {
        default:
          "bg-primary text-primary-foreground shadow-[var(--shadow-button-raised)] hover:bg-[var(--primary-hover)] active:bg-[var(--primary-pressed)] disabled:bg-[var(--bh-interactive-brand-disabled)] disabled:text-[var(--bh-content-disabled)]",
        danger:
          "bg-destructive text-destructive-foreground shadow-[var(--shadow-button-raised)] hover:bg-[var(--destructive-hover)] active:bg-[var(--destructive-pressed)] focus-visible:shadow-[var(--shadow-button-danger-focus)] disabled:bg-[var(--bh-interactive-danger-disabled)] disabled:text-[var(--bh-content-disabled)]",
        destructive:
          "bg-destructive text-destructive-foreground shadow-[var(--shadow-button-raised)] hover:bg-[var(--destructive-hover)] active:bg-[var(--destructive-pressed)] focus-visible:shadow-[var(--shadow-button-danger-focus)] disabled:bg-[var(--bh-interactive-danger-disabled)] disabled:text-[var(--bh-content-disabled)]",
        success:
          "bg-success text-success-foreground shadow-[var(--shadow-button-raised)] hover:bg-[var(--success-hover)] active:bg-[var(--success-pressed)] disabled:bg-[var(--bh-interactive-brand-disabled)] disabled:text-[var(--bh-content-disabled)]",
        warning:
          "bg-warning text-warning-foreground shadow-[var(--shadow-button-raised)] hover:bg-[var(--warning-hover)] active:bg-[var(--warning-pressed)] disabled:bg-[var(--bh-interactive-brand-disabled)] disabled:text-[var(--bh-content-disabled)]",
        secondary:
          "bg-secondary text-secondary-foreground shadow-[var(--shadow-button-secondary)] [--bh-button-secondary-border:var(--bh-border-default)] hover:bg-[var(--secondary-hover)] active:bg-[var(--secondary-pressed)] focus-visible:[--bh-button-secondary-focus-border:var(--bh-border-brand-strong)] focus-visible:shadow-[var(--shadow-button-secondary-focus)] disabled:border disabled:border-[var(--bh-border-disabled)] disabled:bg-[var(--bh-interactive-secondary-disabled)] disabled:text-[var(--bh-content-disabled)]",
        soft:
          "border border-transparent bg-[var(--soft)] text-foreground shadow-[var(--shadow-button-soft)] hover:bg-[var(--soft-hover)] active:bg-[var(--soft-pressed)] focus-visible:border-[var(--bh-border-brand-strong)] disabled:bg-[var(--bh-interactive-soft-disabled)] disabled:text-[var(--bh-content-disabled)]",
        outline:
          "border border-[var(--bh-border-default)] bg-[var(--outline)] text-foreground hover:bg-[var(--outline-hover)] active:bg-[var(--outline-pressed)] focus-visible:border-[var(--bh-border-brand-strong)] disabled:border-[var(--bh-border-disabled)] disabled:bg-[var(--bh-interactive-outlined-disabled)] disabled:text-[var(--bh-content-disabled)]",
        ghost:
          "border border-transparent bg-[var(--ghost)] text-foreground hover:bg-[var(--ghost-hover)] active:bg-[var(--ghost-pressed)] focus-visible:border-[var(--bh-border-brand-strong)] disabled:bg-[var(--bh-interactive-ghost-disabled)] disabled:text-[var(--bh-content-disabled)]",
        "ghost-primary":
          "border border-transparent bg-[var(--ghost)] text-[var(--bh-content-brand-default)] hover:bg-[var(--ghost-hover)] active:bg-[var(--ghost-pressed)] focus-visible:border-[var(--bh-border-brand-strong)] disabled:bg-[var(--bh-interactive-ghost-disabled)] disabled:text-[var(--bh-content-disabled)]",
        white:
          "border border-transparent bg-[var(--bh-bg-always-white)] text-[var(--bh-content-on-light)] focus-visible:border-[var(--bh-border-focus)] disabled:opacity-[var(--bh-opacity-30)]",
        "soft-danger":
          "border border-transparent bg-[var(--destructive-soft)] text-[var(--destructive-soft-foreground)] hover:bg-[var(--destructive-soft-hover)] active:bg-[var(--destructive-soft-pressed)] focus-visible:border-[var(--destructive)] focus-visible:shadow-[var(--shadow-button-danger-focus)] disabled:bg-[var(--bh-interactive-danger-soft-disabled)] disabled:text-[var(--bh-content-disabled)]",
        "soft-destructive":
          "border border-transparent bg-[var(--destructive-soft)] text-[var(--destructive-soft-foreground)] hover:bg-[var(--destructive-soft-hover)] active:bg-[var(--destructive-soft-pressed)] focus-visible:border-[var(--destructive)] focus-visible:shadow-[var(--shadow-button-danger-focus)] disabled:bg-[var(--bh-interactive-danger-soft-disabled)] disabled:text-[var(--bh-content-disabled)]",
        link: "bg-[var(--ghost)] text-[var(--bh-content-brand-default)] hover:bg-[var(--ghost-hover)] active:bg-[var(--ghost-pressed)] focus-visible:border-[var(--bh-border-brand-strong)] disabled:text-[var(--bh-content-disabled)]",
      },
      size: {
        xs: "h-[var(--bh-button-xs-height)] gap-[var(--bh-button-gap-xs)] px-[var(--bh-button-xs-padding-x)] py-[var(--bh-button-sm-padding-y)] has-[>svg]:px-[var(--bh-button-xs-padding-x)]",
        sm: "h-[var(--bh-button-sm-height)] gap-[var(--bh-button-gap)] px-[var(--bh-button-sm-padding-x)] py-[var(--bh-button-sm-padding-y)] has-[>svg]:px-[var(--bh-button-sm-padding-x)]",
        default: "h-[var(--bh-button-md-height)] gap-[var(--bh-button-gap)] px-[var(--bh-button-md-padding-x)] py-[var(--bh-button-sm-padding-y)] has-[>svg]:px-[var(--bh-button-md-padding-x)]",
        lg: "h-[var(--bh-button-lg-height)] gap-[var(--bh-button-gap)] px-[var(--bh-button-lg-padding-x)] py-[var(--bh-button-lg-padding-y)] has-[>svg]:px-[var(--bh-button-lg-padding-x)]",
        xl: "h-[var(--bh-button-xl-height)] gap-[var(--bh-button-gap)] px-[var(--bh-button-lg-padding-x)] py-[var(--bh-button-xl-padding-y)] has-[>svg]:px-[var(--bh-button-lg-padding-x)]",
        "icon-xs": "size-[var(--bh-button-xs-height)] gap-[var(--bh-space-none)] p-[var(--bh-space-none)]",
        "icon-sm": "size-[var(--bh-button-sm-height)] gap-[var(--bh-space-none)] p-[var(--bh-space-none)]",
        icon: "size-[var(--bh-button-md-height)] gap-[var(--bh-space-none)] p-[var(--bh-space-none)]",
        "icon-lg": "size-[var(--bh-button-lg-height)] gap-[var(--bh-space-none)] p-[var(--bh-space-none)]",
        "icon-xl": "size-[var(--bh-button-xl-height)] gap-[var(--bh-space-none)] p-[var(--bh-space-none)]",
      },
    },
    defaultVariants: {
      variant: "default",
      size: "default",
    },
  }
)

type ButtonProps = React.ComponentProps<"button"> &
  VariantProps<typeof buttonVariants> & {
    asChild?: boolean
  }

const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(function Button({
  className,
  variant,
  size,
  asChild = false,
  children,
  ...props
}, ref) {
  const Comp = asChild ? Slot : "button"

  return (
    <Comp
      data-slot="button"
      ref={ref}
      className={cn(buttonVariants({ variant, size, className }))}
      {...props}
    >
      {asChild ? children : <ButtonChildren>{children}</ButtonChildren>}
    </Comp>
  )
})

function ButtonChildren({ children }: { children: React.ReactNode }) {
  return React.Children.map(children, (child) => {
    if (typeof child === "string" || typeof child === "number") {
      return (
        <span data-slot="button-label" dir="auto" className="min-w-0 px-[var(--bh-button-label-padding-x)]">
          {child}
        </span>
      )
    }

    return child
  })
}

export { Button, buttonVariants }
export type { ButtonProps }
