'use client'

import { ReactNode, forwardRef, useState, useRef, useEffect, ButtonHTMLAttributes } from 'react'

type ButtonProps = {
  title?: string
  children?: ReactNode
  onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void
  onToggle?: (open: boolean) => void
  modalId?: string
  color?: 'blue' | 'red' | 'gray' | 'green' | 'teal' | 'transparent'
  variant?: 'solid' | 'outline' | 'ghost' | 'soft' | 'white' | 'link'
  /** Steuert NUR Höhe/Abstände */
  size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'full'
  /** Optionale Schriftgröße */
  textSize?: 'xs' | 'sm' | 'base' | 'lg' | 'xl' | '2xl' | '3xl'
  className?: string
  dropDirection?: 'up' | 'down' | 'auto'
  disabled?: boolean
  loading?: boolean
} & ButtonHTMLAttributes<HTMLButtonElement>

const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button(
  {
    title,
    children,
    onClick,
    onToggle,
    modalId,
    color = 'blue',
    variant = 'solid',
    size = 'md',
    textSize = 'sm',
    className,
    dropDirection = 'down',
    disabled = false,
    loading = false,
    ...rest
  },
  ref
) {
  const [open, setOpen] = useState(false)
  const [direction, setDirection] = useState<'up' | 'down'>('down')
  const localRef = useRef<HTMLButtonElement>(null)
  const buttonRef = (ref as React.RefObject<HTMLButtonElement>) || localRef

  const modalAttributes: { [key: string]: string } = modalId
    ? {
        'aria-haspopup': 'dialog',
        'aria-expanded': 'false',
        'aria-controls': modalId,
        'data-hs-overlay': `#${modalId}`,
      }
    : {}

  // Feste Höhen sorgen für vertikale Zentrierung
  const sizeClasses: Record<NonNullable<ButtonProps['size']>, string> = {
    xs: 'h-7 px-2',
    sm: 'h-8 px-3',
    md: 'h-9 px-4',
    lg: 'h-10 px-5',
    xl: 'h-12 px-6',
    full: 'h-12 px-6 w-full',
  }

  // Nur Textgröße
  const textSizeClasses: Record<NonNullable<ButtonProps['textSize']>, string> = {
    xs: 'text-xs',
    sm: 'text-sm',
    base: 'text-base',
    lg: 'text-lg',
    xl: 'text-xl',
    '2xl': 'text-2xl',
    '3xl': 'text-3xl',
  }

  const base = `
    ${sizeClasses[size] || sizeClasses['md']}
    inline-flex items-center gap-x-2 ${textSizeClasses[textSize] || 'text-sm'}
    font-medium rounded-lg leading-none
    focus:outline-hidden disabled:opacity-50 disabled:cursor-not-allowed
  `

  const variants: Record<string, Record<string, string>> = {
    solid: {
      blue: 'bg-blue-600 text-white hover:bg-blue-700 focus:bg-blue-700',
      red: 'bg-red-600 text-white hover:bg-red-700 focus:bg-red-700',
      gray: 'bg-gray-600 text-white hover:bg-gray-700 focus:bg-gray-700',
      teal: 'bg-teal-600 text-white hover:bg-teal-700 focus:bg-teal-700',
      green: 'bg-green-600 text-white hover:bg-green-700 focus:bg-green-700',
      transparent: 'bg-transparent-600 text-white hover:bg-transparent-700 focus:bg-transparent-700',
    },
    outline: {
      blue: 'border border-gray-200 text-gray-500 hover:border-blue-600 hover:text-blue-600 focus:border-blue-600 focus:text-blue-600 dark:border-neutral-700 dark:text-neutral-400 dark:hover:text-blue-500 dark:hover:border-blue-600 dark:focus:text-blue-500 dark:focus:border-blue-600',
      red: 'border border-gray-200 text-gray-500 hover:border-red-600 hover:text-red-600 focus:border-red-600 focus:text-red-600 dark:border-neutral-700 dark:text-neutral-400 dark:hover:text-red-500 dark:hover:border-red-600 dark:focus:text-red-500 dark:focus:border-red-600',
      gray: 'border border-gray-200 text-gray-500 hover:border-gray-600 hover:text-gray-600 focus:border-gray-600 focus:text-gray-600 dark:border-neutral-700 dark:text-neutral-400 dark:hover:text-white dark:hover:border-neutral-600 dark:focus:text-white dark:focus:border-neutral-600',
      teal: 'border border-teal-200 text-teal-500 hover:border-teal-600 hover:text-teal-600 focus:border-teal-600 focus:text-teal-600 dark:border-neutral-700 dark:text-neutral-400 dark:hover:text-white dark:hover:border-neutral-600 dark:focus:text-white dark:focus:border-neutral-600',
      green: 'border border-green-200 text-green-500 hover:border-green-600 hover:text-green-600 focus:border-green-600 focus:text-green-600 dark:border-neutral-700 dark:text-neutral-400 dark:hover:text-white dark:hover:border-neutral-600 dark:focus:text-white dark:focus:border-neutral-600',
      transparent: 'border border-white/20 bg-transparent text-white shadow-2xs hover:bg-white/15 focus:bg-white/15 dark:bg-transparent dark:border-neutral-700 dark:text-white dark:hover:bg-neutral-700/50 dark:focus:bg-neutral-700/50',
    },
    ghost: {
      blue: 'border border-transparent text-blue-600 hover:bg-blue-100 hover:text-blue-800 focus:bg-blue-100 focus:text-blue-800 dark:text-blue-500 dark:hover:bg-blue-800/30 dark:hover:text-blue-400 dark:focus:bg-blue-800/30 dark:focus:text-blue-400',
      red: 'border border-transparent text-red-600 hover:bg-red-100 hover:text-red-800 focus:bg-red-100 focus:text-red-800 dark:text-red-500 dark:hover:bg-red-800/30 dark:hover:text-red-400 dark:focus:bg-red-800/30 dark:focus:text-red-400',
      gray: 'border border-transparent text-gray-600 hover:bg-gray-100 hover:text-gray-800 focus:bg-gray-100 focus:text-gray-800 dark:text-neutral-400 dark:hover:bg-neutral-700 dark:hover:text-white dark:focus:bg-neutral-700 dark:focus:text-white',
      teal: 'border border-transparent text-teal-600 hover:bg-teal-100 hover:text-teal-800 focus:bg-teal-100 focus:text-teal-800 dark:text-neutral-400 dark:hover:bg-neutral-700 dark:hover:text-white dark:focus:bg-neutral-700 dark:focus:text-white',
      green: 'border border-transparent text-green-600 hover:bg-green-100 hover:text-green-800 focus:bg-green-100 focus:text-green-800 dark:text-neutral-400 dark:hover:bg-neutral-700 dark:focus:bg-neutral-700 dark:focus:text-white',
      transparent: 'border border-transparent text-white hover:bg-white/10 focus:bg-white/10 dark:text-white',
    },
    soft: {
      blue: 'bg-blue-100 text-blue-800 hover:bg-blue-200 focus:bg-blue-200 dark:text-blue-400 dark:hover:bg-blue-900 dark:focus:bg-blue-900',
      red: 'bg-red-100 text-red-800 hover:bg-red-200 focus:bg-red-200 dark:text-red-400 dark:hover:bg-red-900 dark:focus:bg-red-900',
      gray: 'bg-gray-100 text-gray-800 hover:bg-gray-200 focus:bg-gray-200 dark:text-neutral-300 dark:hover:bg-neutral-700 dark:focus:bg-neutral-700',
      teal: 'bg-teal-100 text-teal-800 hover:bg-teal-200 focus:bg-teal-200 dark:text-neutral-300 dark:hover:bg-neutral-700 dark:focus:bg-neutral-700',
      green: 'bg-green-100 text-green-800 hover:bg-green-200 focus:bg-green-200 dark:text-neutral-300 dark:hover:bg-neutral-700 dark:focus:bg-neutral-700',
      transparent: 'bg-transparent-100 text-transparent-800 hover:bg-transparent-200 focus:bg-transparent-200 dark:text-neutral-300 dark:hover:bg-neutral-700 dark:focus:bg-neutral-700',
    },
    white: {
      blue: 'border border-teal-200 bg-white text-gray-800 shadow-2xs hover:bg-gray-50 focus:bg-gray-50 dark:bg-neutral-800 dark:border-neutral-700 dark:text-white dark:hover:bg-neutral-700 dark:focus:bg-neutral-700',
      red: 'border border-gray-200 bg-white text-gray-800 shadow-2xs hover:bg-gray-50 focus:bg-gray-50 dark:bg-neutral-800 dark:border-neutral-700 dark:text-white dark:hover:bg-neutral-700 dark:focus:bg-neutral-700',
      gray: 'border border-gray-200 bg-white text-gray-800 shadow-2xs hover:bg-gray-50 focus:bg-gray-50 dark:bg-neutral-800 dark:border-neutral-700 dark:text-white dark:hover:bg-neutral-700 dark:focus:bg-neutral-700',
      teal: 'border border-teal-200 bg-white text-teal-800 shadow-2xs hover:bg-teal-50 focus:bg-teal-50 dark:bg-neutral-800 dark:border-neutral-700 dark:text-white dark:hover:bg-neutral-700 dark:focus:bg-neutral-700',
      green: 'border border-green-200 bg-white text-green-800 shadow-2xs hover:bg-green-50 focus:bg-green-50 dark:bg-neutral-800 dark:border-neutral-700 dark:text-white dark:hover:bg-neutral-700 dark:focus:bg-neutral-700',
      transparent: 'border border-white/20 bg-transparent text-white shadow-2xs hover:bg-white/15 focus:bg-white/15 dark:bg-transparent dark:border-neutral-700 dark:text-white dark:hover:bg-neutral-700/50 dark:focus:bg-neutral-700/50',
    },
    link: {
      blue: 'border border-transparent text-blue-600 hover:text-blue-800 focus:text-blue-800 dark:text-blue-500 dark:hover:text-blue-400 dark:focus:text-blue-400',
      red: 'border border-transparent text-red-600 hover:text-red-800 focus:text-red-800 dark:text-red-500 dark:hover:text-red-400 dark:focus:text-red-400',
      gray: 'border border-transparent text-gray-600 hover:text-gray-800 focus:text-gray-800 dark:text-neutral-400 dark:hover:text-white dark:focus:text-white',
      teal: 'border border-transparent text-teal-600 hover:text-teal-800 focus:text-teal-800 dark:text-neutral-400 dark:hover:text-white dark:focus:text-white',
      green: 'border border-transparent text-green-600 hover:text-green-800 focus:text-green-800 dark:text-neutral-400 dark:hover:text-white dark:focus:text-white',
      transparent: 'border border-transparent text-transparent-600 hover:text-transparent-800 focus:text-transparent-800 dark:text-neutral-400 dark:hover:text-white dark:focus:text-white',
    },
  }

  const variantClasses = variants[variant]?.[color] || variants.solid.blue

  const stripInteractive = (cls: string) =>
    cls
      .split(/\s+/)
      .filter(c => c && !c.includes('hover:') && !c.includes('focus:') && !c.includes('active:'))
      .join(' ')

  const safeVariantClasses =
    disabled || loading ? stripInteractive(variantClasses) : variantClasses

  const classes = `
    ${base}
    ${safeVariantClasses}
    ${className || ''}
  `

  useEffect(() => {
    if (open && dropDirection === 'auto' && buttonRef.current) {
      requestAnimationFrame(() => {
        const rect = buttonRef.current!.getBoundingClientRect()
        const dropdownHeight = 200
        const spaceBelow = window.innerHeight - rect.bottom
        const spaceAbove = rect.top
        setDirection(spaceBelow < dropdownHeight && spaceAbove > dropdownHeight ? 'up' : 'down')
      })
    }
  }, [open, dropDirection])

  const toggle = (event: React.MouseEvent<HTMLButtonElement>) => {
    const next = !open
    setOpen(next)
    onToggle?.(next)
    onClick?.(event)
  }

  return (
    <button
      ref={buttonRef}
      type="button"
      className={classes}
      onClick={toggle}
      disabled={disabled || loading}
      {...modalAttributes}
      {...rest}
    >
      {loading && (
        <span
          className="animate-spin inline-block size-4 border-[3px] border-current border-t-transparent rounded-full mr-2"
          role="status"
          aria-label="loading"
        />
      )}
      {children ?? title}
    </button>
  )
})

export default Button
