import React, { forwardRef, ButtonHTMLAttributes, ReactNode } from 'react';
import { cn } from '../../lib/utils';
import { getViewport, getTouchTargetSize } from '../../lib/responsive';

// Button variants
type ButtonVariant = 'primary' | 'secondary' | 'outline' | 'ghost';

// Button sizes
type ButtonSize = 'sm' | 'md' | 'lg';

// Button props interface
interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
  variant?: ButtonVariant;
  size?: ButtonSize;
  loading?: boolean;
  icon?: ReactNode;
  iconPosition?: 'left' | 'right';
  fullWidth?: boolean;
  responsiveSize?: {
    mobile?: ButtonSize;
    tablet?: ButtonSize;
    desktop?: ButtonSize;
  };
  touchTarget?: boolean;
}

// Helper function to get variant styles
const getVariantStyles = (variant: ButtonVariant, disabled?: boolean) => {
  const baseStyles = 'transition-all duration-200 ease-in-out font-medium rounded-lg focus:outline-none focus:ring-2 focus:ring-offset-2';
  
  if (disabled) {
    return `${baseStyles} bg-gray-300 text-gray-500 cursor-not-allowed opacity-60`;
  }

  switch (variant) {
    case 'primary':
      return `${baseStyles} bg-primary hover:bg-primary-dark text-white focus:ring-primary`;
    case 'secondary':
      return `${baseStyles} bg-secondary hover:bg-secondary-light text-white focus:ring-secondary`;
    case 'outline':
      return `${baseStyles} bg-transparent border-2 border-primary text-primary hover:bg-primary-light hover:border-primary-dark focus:ring-primary`;
    case 'ghost':
      return `${baseStyles} bg-transparent text-primary hover:bg-primary-light focus:ring-primary`;
    default:
      return `${baseStyles} bg-primary hover:bg-primary-dark text-white`;
  }
};

// Helper function to get size styles
const getSizeStyles = (size: ButtonSize) => {
  switch (size) {
    case 'sm':
      return 'px-3 py-1.5 text-sm';
    case 'md':
      return 'px-4 py-2 text-base';
    case 'lg':
      return 'px-6 py-3 text-lg';
    default:
      return 'px-4 py-2 text-base';
  }
};

// Helper function to get icon spacing
const getIconSpacing = (size: ButtonSize, iconPosition: 'left' | 'right') => {
  const spacing = {
    sm: iconPosition === 'left' ? 'mr-1.5' : 'ml-1.5',
    md: iconPosition === 'left' ? 'mr-2' : 'ml-2',
    lg: iconPosition === 'left' ? 'mr-2.5' : 'ml-2.5',
  };
  return spacing[size];
};

// Loading spinner component
const LoadingSpinner = ({ size }: { size: ButtonSize }) => {
  const sizeClasses = {
    sm: 'w-4 h-4',
    md: 'w-5 h-5',
    lg: 'w-6 h-6',
  };

  return (
    <div className={cn('animate-spin', sizeClasses[size])}>
      <svg
        className="w-full h-full text-current"
        xmlns="http://www.w3.org/2000/svg"
        fill="none"
        viewBox="0 0 24 24"
      >
        <circle
          className="opacity-25"
          cx="12"
          cy="12"
          r="10"
          stroke="currentColor"
          strokeWidth="4"
        ></circle>
        <path
          className="opacity-75"
          fill="currentColor"
          d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
        ></path>
      </svg>
    </div>
  );
};

// Main Button component
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
  (
    {
      variant = 'primary',
      size = 'md',
      loading = false,
      icon,
      iconPosition = 'left',
      fullWidth = false,
      disabled,
      className = '',
      children,
      type = 'button',
      responsiveSize,
      touchTarget = true,
      ...props
    },
    ref
  ) => {
    const isDisabled = disabled || loading;
    
    // Get responsive size if provided
    const getResponsiveSize = () => {
      if (!responsiveSize) return size;
      
      if (typeof window === 'undefined') return size;
      
      const viewport = getViewport();
      
      if (viewport.isMobile && responsiveSize.mobile) {
        return responsiveSize.mobile;
      }
      if (viewport.isTablet && responsiveSize.tablet) {
        return responsiveSize.tablet;
      }
      if (viewport.isDesktop && responsiveSize.desktop) {
        return responsiveSize.desktop;
      }
      
      return size;
    };

    const responsiveSizeValue = getResponsiveSize();
    
    // Get touch target size
    const getTouchTargetClasses = () => {
      if (!touchTarget) return '';
      
      if (typeof window === 'undefined') return '';
      
      const viewport = getViewport();
      const targetSize = getTouchTargetSize(viewport.isMobile, viewport.isLargeDesktop);
      
      // Ensure minimum touch target
      return `min-h-[44px] min-w-[44px]`;
    };

    return (
      <button
        ref={ref}
        type={type}
        disabled={isDisabled}
        className={cn(
          'inline-flex items-center justify-center font-semibold',
          'transition-all duration-200 ease-in-out',
          'focus:outline-none focus:ring-2 focus:ring-offset-2',
          // Base styles
          'rounded-lg',
          // Variant styles
          getVariantStyles(variant, isDisabled),
          // Size styles (responsive)
          getSizeStyles(responsiveSizeValue),
          // Touch target optimization
          getTouchTargetClasses(),
          // Full width
          fullWidth ? 'w-full' : '',
          // Mobile-specific optimizations
          'active:scale-95 md:active:scale-100',
          // Custom classes
          className
        )}
        // Add aria-label for accessibility if button has only icon
        aria-label={!children && icon ? 'Button action' : undefined}
        {...props}
      >
        {/* Loading state */}
        {loading && (
          <span className={cn('flex items-center justify-center', getIconSpacing(responsiveSizeValue, 'left'))}>
            <LoadingSpinner size={responsiveSizeValue} />
          </span>
        )}

        {/* Icon - Left position */}
        {!loading && icon && iconPosition === 'left' && (
          <span className={cn('flex items-center justify-center', getIconSpacing(responsiveSizeValue, 'left'))}>
            {icon}
          </span>
        )}

        {/* Button content */}
        {children && <span className="leading-none">{children}</span>}

        {/* Icon - Right position */}
        {!loading && icon && iconPosition === 'right' && (
          <span className={cn('flex items-center justify-center', getIconSpacing(responsiveSizeValue, 'right'))}>
            {icon}
          </span>
        )}
      </button>
    );
  }
);

Button.displayName = 'Button';

// Export types for external use
export type { ButtonProps, ButtonVariant, ButtonSize };