import {
  RefObject,
  CSSProperties,
  useState,
  useRef,
  useEffect,
  useMemo,
} from 'react';

/**
 * Utility functions for hover preview styling
 */

export type IconSize = 'large' | 'small';
export function iconClassNamesForSize(size: IconSize) {
  switch (size) {
    case 'large':
      return 'h-8 w-8 flex-shrink-0 rounded-md';
    case 'small':
      return 'h-5 w-5 flex-shrink-0 rounded-sm';
  }
}

// Base preview container styling
export const getPreviewContainerClassName = (
  maxWidth: string,
  maxHeight: string,
) => {
  // calculate if the page is mobile
  const isMobile = window.innerWidth < 640;
  return [
    isMobile ? 'hidden' : '',
    `max-w-[${maxWidth}] max-h-[${maxHeight}] rounded-lg`,
    'border border-slate-400 bg-slate-100',
    'divide-y divide-slate-300',
    'shadow-lg shadow-slate-500/30',
  ].join(' ');
};

// Header/Footer styling
export const getHeaderFooterClassName = () => {
  return [
    'flex items-center overflow-hidden',
    'border-slate-400 bg-gradient-to-r from-slate-200 to-slate-300 p-2',
  ].join(' ');
};

// Content area styling
export const getContentClassName = () => {
  return 'bg-slate-100 p-3';
};

// Text styling functions
export const getHeaderTextClassName = () => {
  return 'mr-2 min-w-0 truncate text-sm font-semibold text-slate-700';
};

export const getLabelTextClassName = () => {
  return 'text-2xs text-slate-700';
};

export const getValueTextClassName = () => {
  return 'block text-sm font-semibold text-slate-700';
};

export const getSecondaryTextClassName = () => {
  return 'text-sm italic text-slate-600';
};

// Border and shadow styling
export const getBorderClassName = () => {
  return 'border border-slate-300';
};

// Avatar container styling
export const getAvatarContainerClassName = () => {
  return 'overflow-hidden rounded-md';
};

// Base avatar image styling
export const getAvatarImageClassName = (size: string = 'medium') => {
  const sizeClasses = {
    small: 'h-6 w-6',
    medium: 'h-[80px] w-[80px]',
    large: 'h-20 w-20',
  };

  return `${sizeClasses[size as keyof typeof sizeClasses]} rounded-md ${getBorderClassName()} object-cover shadow-sm`;
};

// Icon styling
export const getIconClassName = () => {
  return 'h-8 w-8 rounded-md p-1';
};

/**
 * Calculate the position for a hover preview popup
 * @param containerRef The reference to the element containing the hover trigger
 * @param previewRef The reference to the popup element
 * @returns CSS properties for positioning the popup or undefined if refs are not available
 */
export const calculatePreviewPosition = (
  containerRef: RefObject<HTMLElement>,
  previewRef: RefObject<HTMLElement>,
): CSSProperties | undefined => {
  if (!containerRef.current || !previewRef.current) return undefined;

  // Get dimensions
  const linkRect = containerRef.current.getBoundingClientRect();
  const previewRect = previewRef.current.getBoundingClientRect();
  const viewport = {
    width: window.innerWidth,
    height: window.innerHeight,
  };

  // Determine horizontal position
  const spaceRight = viewport.width - linkRect.right;
  const spaceLeft = linkRect.left;
  const showOnRight = spaceRight > spaceLeft;

  // Calculate vertical center alignment
  const linkCenter = linkRect.top + linkRect.height / 2;
  const padding =
    parseInt(getComputedStyle(document.documentElement).fontSize) * 2; // 2em

  // Calculate preferred vertical position (centered with link)
  let top = linkCenter - previewRect.height / 2;

  // Adjust if too close to viewport edges
  if (top < padding) top = padding;
  if (top + previewRect.height > viewport.height - padding) {
    top = viewport.height - previewRect.height - padding;
  }

  // Return position
  return {
    position: 'fixed',
    zIndex: 9999,
    top: `${top}px`,
    overflow: 'auto',
    transition: 'opacity 0.2s ease-in-out',
    ...(showOnRight
      ? { left: `${linkRect.right + 10}px` }
      : { right: `${viewport.width - linkRect.left + 10}px` }),
  };
};

/**
 * Get initial offscreen position style for measurement
 */
export const getOffscreenMeasurementStyle = (): CSSProperties => {
  return {
    position: 'fixed',
    left: '-9999px',
    top: '0',
    opacity: '0',
    transition: 'opacity 0.2s ease-in-out',
  };
};

/**
 * Custom hook for handling hover preview functionality
 */
export const useHoverPreview = () => {
  const [showPreview, setShowPreview] = useState(false);
  const [previewStyle, setPreviewStyle] = useState<CSSProperties>({});
  const containerRef = useRef<HTMLDivElement>(null);
  const previewRef = useRef<HTMLDivElement>(null);

  // Create portal container once
  const portalContainer = useMemo(() => document.createElement('div'), []);

  // Setup portal container
  useEffect(() => {
    document.body.appendChild(portalContainer);
    return () => {
      document.body.removeChild(portalContainer);
    };
  }, [portalContainer]);

  // Position and display the preview
  const updatePosition = () => {
    const newPosition = calculatePreviewPosition(containerRef, previewRef);
    if (newPosition) {
      setPreviewStyle(newPosition);
    }
  };

  // Two-step approach: first measure offscreen, then show
  const handleMouseEnter = () => {
    // Step 1: Render offscreen for measurement
    setPreviewStyle(getOffscreenMeasurementStyle());
    setShowPreview(true);

    // Step 2: Position properly after a very short delay
    setTimeout(() => {
      updatePosition();
    }, 20);
  };

  const handleMouseLeave = () => {
    setShowPreview(false);
  };

  // Handle window resize
  useEffect(() => {
    if (!showPreview) return;

    window.addEventListener('resize', updatePosition);
    return () => {
      window.removeEventListener('resize', updatePosition);
    };
  }, [showPreview]);

  return {
    containerRef,
    previewRef,
    portalContainer,
    showPreview,
    previewStyle,
    handleMouseEnter,
    handleMouseLeave,
  };
};

export function anchorClassNamesForVisualStyle(
  visualStyle: string,
  hasIcon: boolean = false,
) {
  let classNames = ['truncate', 'gap-1'];
  if (hasIcon) {
    classNames.push('flex items-center');
  }
  return classNames.join(' ');
}
