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 }
