import { forwardRef, useState } from 'react'
import type { ButtonHTMLAttributes, ReactNode } from 'react'
import { cva, type VariantProps } from 'class-variance-authority'
import { cn } from '@/lib/utils'
import { motion } from 'framer-motion'
import {
  FolderLine,
  FolderFillLine,
  ArrowRightLine,
  CloseLine,
} from '../basic/icons-inline'

const folderButtonVariants = cva(
  'inline-flex items-center justify-center gap-2 font-medium transition-colors duration-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-border focus-visible:ring-offset-2 focus-visible:ring-offset-bg-base group',
  {
    variants: {
      size: {
        sm: 'h-[var(--control-height-sm)] px-[var(--control-padding-x-sm)] text-[length:var(--control-font-size-sm)] leading-[var(--control-line-height-sm)]',
        md: 'h-[var(--control-height-md)] px-[var(--control-padding-x-md)] text-[length:var(--control-font-size-md)] leading-[var(--control-line-height-md)]',
        lg: 'h-[var(--control-height-lg)] px-[var(--control-padding-x-lg)] text-[length:var(--control-font-size-lg)] leading-[var(--control-line-height-lg)]',
      },
      rounded: {
        square: 'rounded',
        pill: 'rounded-full',
      },
      selected: {
        true: 'bg-info-bg text-info',
        false: 'bg-fill-tertiary text-text hover:bg-fill-secondary',
      },
    },
    defaultVariants: {
      size: 'md',
      rounded: 'square',
      selected: false,
    },
  }
)

const iconClass = 'w-4 h-4'

export interface FolderButtonProps
  extends ButtonHTMLAttributes<HTMLButtonElement>,
    VariantProps<typeof folderButtonVariants> {
  label: string
  selected?: boolean
  disabled?: boolean
  multipleFolders?: boolean
  onClear?: () => void
  folderIcon?: ReactNode
  folderFillIcon?: ReactNode
  arrowRightIcon?: ReactNode
  closeIcon?: ReactNode
}

export const FolderButton = forwardRef<HTMLButtonElement, FolderButtonProps>(
  (
    {
      label,
      selected = false,
      disabled = false,
      multipleFolders = false,
      onClear,
      size = 'md',
      rounded = 'square',
      className,
      onMouseEnter: onMouseEnterProp,
      onMouseLeave: onMouseLeaveProp,
      folderIcon,
      folderFillIcon,
      arrowRightIcon,
      closeIcon,
      ...props
    },
    ref
  ) => {
    const [isHovered, setIsHovered] = useState(false)
    const [isClearFocused, setIsClearFocused] = useState(false)
    const showClose = selected && !disabled && !multipleFolders && typeof onClear === 'function'
    const showClearControl = isHovered || isClearFocused

    const baseStyles = cn(
      folderButtonVariants({ size, rounded, selected, className }),
      disabled && 'opacity-50 cursor-not-allowed',
      !disabled && 'cursor-pointer'
    )

    const handleMouseEnter = (e: React.MouseEvent<HTMLButtonElement>) => {
      if (showClose) setIsHovered(true)
      onMouseEnterProp?.(e)
    }
    const handleMouseLeave = (e: React.MouseEvent<HTMLButtonElement>) => {
      if (showClose) setIsHovered(false)
      onMouseLeaveProp?.(e)
    }

    const defaultFolder = folderIcon ?? <FolderLine className={iconClass} />
    const defaultFolderFill = folderFillIcon ?? <FolderFillLine className={iconClass} />
    const defaultArrow = arrowRightIcon ?? <ArrowRightLine className={iconClass} />
    const defaultClose = closeIcon ?? <CloseLine className={iconClass} />

    const content = (
      <>
        <span className="w-4 h-4 flex items-center justify-center flex-shrink-0 relative text-current">
          {selected ? defaultFolderFill : defaultFolder}
        </span>

        <span>{label}</span>

        {multipleFolders && (
          <span className="w-4 h-4 flex items-center justify-center flex-shrink-0">
            {defaultArrow}
          </span>
        )}

        {showClose ? (
          <motion.span
            role="button"
            tabIndex={0}
            aria-label="清空文件夹选择"
            className="flex items-center justify-center flex-shrink-0 rounded-sm text-info hover:text-info-hover cursor-pointer overflow-hidden focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-border"
            initial={false}
            animate={{
              width: showClearControl ? 20 : 0,
              opacity: showClearControl ? 1 : 0,
              marginLeft: showClearControl ? 2 : 0,
            }}
            transition={{ duration: 0.2, ease: 'easeOut' }}
            style={{ pointerEvents: showClearControl ? 'auto' : 'none', minWidth: 0 }}
            onFocus={() => setIsClearFocused(true)}
            onBlur={() => setIsClearFocused(false)}
            onPointerDown={(e) => {
              e.preventDefault()
              e.stopPropagation()
            }}
            onClick={(e) => {
              e.preventDefault()
              e.stopPropagation()
              onClear()
            }}
            onKeyDown={(e) => {
              if (e.key === 'Enter' || e.key === ' ') {
                e.preventDefault()
                e.stopPropagation()
                onClear()
              }
            }}
          >
            <span className="w-4 h-4 flex items-center justify-center flex-shrink-0">
              {defaultClose}
            </span>
          </motion.span>
        ) : null}
      </>
    )

    return (
      <button
        ref={ref}
        className={baseStyles}
        disabled={disabled}
        onMouseEnter={handleMouseEnter}
        onMouseLeave={handleMouseLeave}
        {...props}
      >
        {content}
      </button>
    )
  }
)

FolderButton.displayName = 'FolderButton'

export { folderButtonVariants }
