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"

// Loading 图标组件
export const LoadingIcon = ({ className }: { className?: string }) => (
  <i className={cn("iconfont icon-loading animate-spin", className)} />
)

const buttonVariants = cva(
  "inline-flex items-center justify-center gap-2 whitespace-nowrap transition-all disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_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 cursor-pointer",
  {
    variants: {
      variant: {
        primary:
          "bg-primary-gradient-normal disabled:bg-none disabled:bg-primary-variant-disabled disabled:text-txt-primary-disabled disabled:backdrop-blur-lg text-txt-primary-specialmap-normal shadow-xs hover:bg-primary-gradient-hover active:bg-primary-gradient-press",
        secondary: "border border-solid border-primary-variant-normal text-primary-variant-normal disabled:border-primary-variant-disabled disabled:text-txt-primary-disabled hover:border-primary-variant-hover hover:text-primary-variant-hover active:border-primary-variant-press active:text-primary-variant-press",
        tertiary: "bg-surface-element-normal text-txt-primary-normal disabled:bg-surface-element-disabled disabled:text-txt-primary-disabled hover:bg-surface-element-hover active:bg-surface-element-press",
        tertiaryDark: "bg-surface-element-dark-normal text-txt-primary-normal disabled:bg-surface-element-dark-disabled disabled:text-txt-primary-disabled hover:bg-surface-element-dark-hover active:bg-surface-element-dark-press",
        destructive: "bg-important-normal text-txt-primary-normal disabled:bg-important-disabled disabled:text-txt-primary-disabled disabled:backdrop-blur-lg hover:bg-important-hover active:bg-important-press",
        ghost: "bg-transparent text-primary-variant-normal disabled:text-txt-primary-disabled hover:bg-surface-element-hover hover:backdrop-blur-[16px] active:bg-surface-element-press",
        vip: "bg-gradient-secondary-normal text-black"
      },
      size: {
        large: "min-w-[128px] h-12 rounded-full px-8 has-[>svg]:px-6 txt-label-l",
        small: "min-w-[80px] h-8 rounded-full px-4 has-[>svg]:px-2 txt-label-s",
        icon: "size-9",
      },
      block: {
        true: "w-full",
        false: "",
      },
      loading: {
        true: "cursor-not-allowed backdrop-blur backdrop-filter",
        false: "",
      },
    },
    defaultVariants: {
      variant: "primary",
      size: "large",
      block: false,
      loading: false,
    },
  }
)

const iconButtonVariants = cva(
  "inline-flex items-center  justify-center transition-all disabled:pointer-events-none [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-none rounded-full cursor-pointer",
  {
    variants: {
      variant: {
        default: "bg-primary-gradient-normal text-txt-primary-normal disabled:bg-primary-gradient-disabled disabled:bg-none disabled:text-txt-primary-disabled hover:bg-primary-gradient-hover active:bg-primary-gradient-press",
        primary: "bg-primary-normal text-txt-primary-normal disabled:bg-primary-disabled disabled:text-txt-primary-disabled hover:bg-primary-hover active:bg-primary-press",
        tertiary: "bg-surface-element-normal text-txt-primary-normal backdrop-blur-lg disabled:bg-surface-element-disabled disabled:text-txt-primary-disabled hover:bg-surface-element-hover active:bg-surface-element-press",
        tertiaryDark: "bg-surface-element-dark-normal text-txt-primary-normal disabled:bg-surface-element-dark-disabled disabled:text-txt-primary-specialmap-disable hover:bg-surface-element-dark-hover active:bg-surface-element-dark-press",
        contrast: "bg-surface-element-light-normal text-txt-primary-normal disabled:bg-surface-element-light-disabled disabled:text-txt-primary-disabled hover:bg-surface-element-light-hover active:bg-surface-element-light-press",
        ghost: "bg-transparent text-txt-primary-normal disabled:text-txt-primary-disabled hover:bg-surface-element-hover hover:backdrop-blur-[16px] active:bg-surface-element-press",
        destructive: "bg-important-normal text-txt-primary-normal disabled:bg-important-disabled disabled:text-txt-primary-disabled disabled:backdrop-blur-lg hover:bg-important-hover active:bg-important-press",
      },
      size: {
        large: "size-12 [&_svg:not([class*='size-'])]:size-6 [&_i]:!text-[24px]",
        small: "size-8 [&_svg:not([class*='size-'])]:size-4 [&_i]:!text-[16px]",
        xs: "size-6 [&_svg:not([class*='size-'])]:size-3 [&_i]:!text-[12px]",
        mini: "size-4 [&_svg:not([class*='size-'])]:size-2 [&_i]:!text-[8px]",
      },
      loading: {
        true: "cursor-not-allowed backdrop-blur backdrop-filter",
        false: "",
      },
    },
    defaultVariants: {
      variant: "default",
      size: "large",
      loading: false,
    },
  }
)

function Button({
  className,
  variant,
  size,
  block,
  loading = false,
  children,
  asChild = false,
  disabled,
  ...props
}: React.ComponentProps<"button"> &
  VariantProps<typeof buttonVariants> & {
    asChild?: boolean,
    block?: boolean,
    loading?: boolean
  }) {
  const Comp = asChild ? Slot : "button"

  // 当 loading 为 true 时，自动禁用按钮
  const isDisabled = disabled || loading

  return (
    <Comp
      data-slot="button"
      className={cn(buttonVariants({ variant, size, className, block, loading }))}
      disabled={isDisabled}
      {...props}
    >
      {loading && (
        <LoadingIcon 
          className={cn(
            size === "large" ? "!text-[24px]" : "!text-[16px]",
            "shrink-0"
          )} 
        />
      )}
      {/* 当 loading 时，如果有 children 则显示，否则只显示 loading 图标 */}
      {!loading ? children : null}
    </Comp>
  )
}

function IconButton({
  className,
  variant,
  iconfont,
  size,
  loading = false,
  children,
  asChild = false,
  disabled,
  ...props
}: React.ComponentProps<"button"> &
  VariantProps<typeof iconButtonVariants> & {
    iconfont?: string,
    asChild?: boolean,
    loading?: boolean
  }) {
  const Comp = asChild ? Slot : "button"

  // 当 loading 为 true 时，自动禁用按钮
  const isDisabled = disabled || loading

  return (
    <Comp
      data-slot="icon-button"
      className={cn(iconButtonVariants({ variant, size, className, loading }))}
      disabled={isDisabled}
      type="button"
      {...props}
    >
      {loading ? (
        <LoadingIcon 
          className={cn(
            size === "large" ? "!text-[24px]" : 
            size === "small" ? "!text-[16px]" : 
            size === "xs" ? "!text-[12px]" : "!text-[8px]"
          )} 
        />
      ) : (
        <>
          {iconfont && <i className={cn("iconfont", iconfont)} />}
          {children}
        </>
      )}
    </Comp>
  )
}

export { Button, IconButton, buttonVariants, iconButtonVariants }
