import React, { forwardRef, HTMLAttributes } from 'react';
import { cn } from '../../lib/utils';

// Loading sizes
type LoadingSize = 'sm' | 'md' | 'lg' | 'xl';

// Loading variants
type LoadingVariant = 'primary' | 'secondary' | 'neutral' | 'contrast';

// Loading props interface
interface LoadingProps extends HTMLAttributes<HTMLDivElement> {
  size?: LoadingSize;
  variant?: LoadingVariant;
  overlay?: boolean;
  text?: string;
  fullscreen?: boolean;
}

// Helper function to get size styles
const getSizeStyles = (size: LoadingSize) => {
  switch (size) {
    case 'sm':
      return 'w-4 h-4 border-2';
    case 'md':
      return 'w-8 h-8 border-4';
    case 'lg':
      return 'w-12 h-12 border-4';
    case 'xl':
      return 'w-16 h-16 border-4';
    default:
      return 'w-8 h-8 border-4';
  }
};

// Helper function to get variant styles
const getVariantStyles = (variant: LoadingVariant) => {
  switch (variant) {
    case 'primary':
      return 'border-primary';
    case 'secondary':
      return 'border-secondary';
    case 'neutral':
      return 'border-gray-300';
    case 'contrast':
      return 'border-white';
    default:
      return 'border-primary';
  }
};

// Helper function to get text size
const getTextSize = (size: LoadingSize) => {
  switch (size) {
    case 'sm':
      return 'text-sm';
    case 'md':
      return 'text-base';
    case 'lg':
      return 'text-lg';
    case 'xl':
      return 'text-xl';
    default:
      return 'text-base';
  }
};

// Main Loading Component
export const Loading = forwardRef<HTMLDivElement, LoadingProps>(
  ({
    size = 'md',
    variant = 'primary',
    overlay = false,
    text,
    fullscreen = false,
    className = '',
    ...props
  }, ref) => {
    const spinner = (
      <div
        className={cn(
          'animate-spin rounded-full',
          'border-t-transparent',
          getSizeStyles(size),
          getVariantStyles(variant),
          className
        )}
        {...props}
      />
    );

    if (overlay) {
      return (
        <div
          ref={ref}
          className={cn(
            'fixed inset-0 z-50 flex items-center justify-center',
            'bg-black/50 backdrop-blur-sm',
            fullscreen && 'w-screen h-screen'
          )}
        >
          <div className="flex flex-col items-center gap-3">
            {spinner}
            {text && (
              <span className={cn('text-white font-medium', getTextSize(size))}>
                {text}
              </span>
            )}
          </div>
        </div>
      );
    }

    return (
      <div
        ref={ref}
        className={cn(
          'flex flex-col items-center justify-center gap-3',
          fullscreen && 'w-screen h-screen'
        )}
      >
        {spinner}
        {text && (
          <span className={cn('text-gray-700 font-medium', getTextSize(size))}>
            {text}
          </span>
        )}
      </div>
    );
  }
);

Loading.displayName = 'Loading';

// Loading Button Component
interface LoadingButtonProps extends HTMLAttributes<HTMLDivElement> {
  size?: LoadingSize;
  variant?: LoadingVariant;
  text?: string;
}

export const LoadingButton = forwardRef<HTMLDivElement, LoadingButtonProps>(
  ({ size = 'md', variant = 'primary', text = 'Loading...', className = '', ...props }, ref) => {
    return (
      <div
        ref={ref}
        className={cn(
          'inline-flex items-center gap-2 px-4 py-2 rounded-lg',
          'bg-gray-100 text-gray-700',
          className
        )}
        {...props}
      >
        <div
          className={cn(
            'animate-spin rounded-full border-t-transparent',
            getSizeStyles(size === 'sm' ? 'sm' : 'md'),
            getVariantStyles(variant)
          )}
        />
        <span className="font-medium">{text}</span>
      </div>
    );
  }
);

LoadingButton.displayName = 'LoadingButton';

// Loading Skeleton Component
interface LoadingSkeletonProps extends HTMLAttributes<HTMLDivElement> {
  width?: string | number;
  height?: string | number;
  rounded?: boolean;
  className?: string;
}

export const LoadingSkeleton = forwardRef<HTMLDivElement, LoadingSkeletonProps>(
  ({ width = '100%', height = '1rem', rounded = false, className = '', ...props }, ref) => {
    // Convert numeric values to Tailwind width classes
    const getWidthClass = (width: string | number) => {
      if (typeof width === 'number') {
        if (width <= 32) return 'w-8';
        if (width <= 64) return 'w-16';
        if (width <= 128) return 'w-32';
        if (width <= 192) return 'w-48';
        if (width <= 256) return 'w-64';
        return 'w-full';
      }
      return width === '100%' ? 'w-full' : width;
    };

    // Convert numeric values to Tailwind height classes
    const getHeightClass = (height: string | number) => {
      if (typeof height === 'number') {
        if (height <= 8) return 'h-2';
        if (height <= 16) return 'h-4';
        if (height <= 24) return 'h-6';
        if (height <= 32) return 'h-8';
        if (height <= 48) return 'h-12';
        if (height <= 64) return 'h-16';
        return 'h-auto';
      }
      return height === '1rem' ? 'h-4' : height;
    };

    return (
      <div
        ref={ref}
        className={cn(
          'animate-pulse bg-gray-200',
          rounded && 'rounded-md',
          getWidthClass(width),
          getHeightClass(height),
          className
        )}
        {...props}
      />
    );
  }
);

LoadingSkeleton.displayName = 'LoadingSkeleton';

// Export types for external use
export type { LoadingProps, LoadingSize, LoadingVariant, LoadingButtonProps, LoadingSkeletonProps };