import * as React from 'react'
import { cva, type VariantProps } from 'class-variance-authority'
import { CheckIcon, CopyIcon } from 'lucide-react'

import { cn } from './utils'

const copyButtonVariants = cva(
  'inline-flex items-center justify-center gap-2 rounded-xl text-[13px] font-semibold transition-all duration-250 cursor-pointer outline-none focus-visible:ring-2 focus-visible:ring-primary/50 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*="size-"])]:size-4',
  {
    variants: {
      variant: {
        default:
          'border border-border-glass bg-glass text-foreground hover:bg-glass-hover hover:border-primary backdrop-blur-[20px]',
        ghost: 'hover:bg-glass-hover text-foreground-secondary hover:text-foreground',
      },
      size: {
        default: 'h-8 px-3',
        sm: 'h-7 px-2 text-[12px]',
        icon: 'size-8',
        'icon-sm': 'size-7',
      },
    },
    defaultVariants: {
      variant: 'default',
      size: 'default',
    },
  }
)

export interface CopyButtonProps
  extends
    Omit<React.ComponentProps<'button'>, 'children'>,
    VariantProps<typeof copyButtonVariants> {
  /** The text to copy to clipboard */
  value: string
  /** Label shown before copying */
  label?: string
  /** Label shown after copying */
  copiedLabel?: string
  /** Duration in ms to show the copied state */
  copiedDuration?: number
  /** Callback fired after successful copy */
  onCopy?: () => void
  /** When true, renders only the icon without text */
  iconOnly?: boolean
}

function CopyButton({
  className,
  variant,
  size,
  value,
  label = 'Copy',
  copiedLabel = 'Copied!',
  copiedDuration = 2000,
  onCopy,
  iconOnly = false,
  ...props
}: CopyButtonProps) {
  const [copied, setCopied] = React.useState(false)
  const timerRef = React.useRef<ReturnType<typeof setTimeout> | null>(null)

  React.useEffect(() => {
    return () => {
      if (timerRef.current) clearTimeout(timerRef.current)
    }
  }, [])

  const handleClick = React.useCallback(() => {
    void navigator.clipboard
      .writeText(value)
      .then(() => {
        setCopied(true)
        onCopy?.()

        if (timerRef.current) clearTimeout(timerRef.current)
        timerRef.current = setTimeout(() => {
          setCopied(false)
          timerRef.current = null
        }, copiedDuration)
      })
      .catch(() => {
        // Clipboard API not available or permission denied
      })
  }, [value, copiedDuration, onCopy])

  return (
    <button
      data-slot="copy-button"
      data-copied={copied || undefined}
      type="button"
      className={cn(
        copyButtonVariants({ variant, size: iconOnly ? 'icon' : size }),
        copied && 'text-accent-cyan border-accent-cyan/30',
        className
      )}
      onClick={handleClick}
      aria-label={iconOnly ? (copied ? copiedLabel : label) : undefined}
      {...props}
    >
      {copied ? (
        <>
          <CheckIcon className="size-3.5" />
          {!iconOnly && <span>{copiedLabel}</span>}
        </>
      ) : (
        <>
          <CopyIcon className="size-3.5" />
          {!iconOnly && <span>{label}</span>}
        </>
      )}
    </button>
  )
}

export { CopyButton, copyButtonVariants }
