import React, { useState, useRef, useCallback, useEffect } from 'react';
import { useIntersectionObserver } from '@/hooks/useIntersectionObserver';

interface OptimizedImageProps {
  src: string;
  alt: string;
  width?: number;
  height?: number;
  className?: string;
  placeholder?: string;
  blurDataURL?: string;
  priority?: boolean;
  quality?: number;
  sizes?: string;
  onLoad?: () => void;
  onError?: () => void;
  fallback?: React.ReactNode;
}

// Configuration des formats supportés
const SUPPORTED_FORMATS = ['webp', 'avif', 'jpeg', 'png', 'gif'];
const FALLBACK_FORMAT = 'jpeg';

// Générer les sources pour différents formats
function generateImageSources(src: string, sizes?: string) {
  const baseUrl = src.replace(/\.[^/.]+$/, '');

  return SUPPORTED_FORMATS.map((format) => {
    const formatSrc = `${baseUrl}.${format}`;
    return {
      src: formatSrc,
      type: `image/${format}`,
      sizes: sizes || '100vw',
    };
  });
}

// Composant de placeholder avec blur
function BlurPlaceholder({
  blurDataURL,
  width,
  height,
  className,
}: {
  blurDataURL?: string;
  width?: number;
  height?: number;
  className?: string;
}) {
  if (!blurDataURL) {
    return (
      <div
        className={`bg-gray-200 animate-pulse ${className}`}
        style={{ width, height }}
      />
    );
  }

  return (
    <img
      src={blurDataURL}
      alt=""
      className={`blur-sm ${className}`}
      style={{ width, height }}
      aria-hidden="true"
    />
  );
}

// Hook pour détecter le support des formats d'image
function useImageFormatSupport() {
  const [supportedFormats, setSupportedFormats] = useState<string[]>([]);

  useEffect(() => {
    const checkFormatSupport = async () => {
      const formats: string[] = [];

      // Test WebP
      const webpSupported = await new Promise<boolean>((resolve) => {
        const webp = new Image();
        webp.onload = webp.onerror = () => resolve(webp.height === 2);
        webp.src =
          'data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA';
      });

      // Test AVIF
      const avifSupported = await new Promise<boolean>((resolve) => {
        const avif = new Image();
        avif.onload = avif.onerror = () => resolve(avif.height === 2);
        avif.src =
          'data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAABcAAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAEAAAABAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQAMAAAAABNjb2xybmNseAACAAIABoAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAAB9tZGF0EgAKCBgABogQEAwgMgkAAAAAAAAG8AAAAA==';
      });

      if (webpSupported) formats.push('webp');
      if (avifSupported) formats.push('avif');
      formats.push('jpeg', 'png', 'gif'); // Formats de base toujours supportés

      setSupportedFormats(formats);
    };

    checkFormatSupport();
  }, []);

  return supportedFormats;
}

export function OptimizedImage({
  src,
  alt,
  width,
  height,
  className = '',
  placeholder,
  blurDataURL,
  priority = false,
  quality: _quality = 75,
  sizes = '100vw',
  onLoad,
  onError,
  fallback,
}: OptimizedImageProps) {
  const [isLoaded, setIsLoaded] = useState(false);
  const [hasError, setHasError] = useState(false);
  const [currentSrc, setCurrentSrc] = useState<string | null>(null);
  const imgRef = useRef<HTMLImageElement>(null);
  const supportedFormats = useImageFormatSupport();

  // Intersection Observer pour le lazy loading
  const intersectionRef = useRef<HTMLDivElement>(null);
  const entry = useIntersectionObserver(intersectionRef, {
    threshold: 0.1,
    rootMargin: '50px',
  });
  const isIntersecting = !!entry?.isIntersecting;

  // Générer les sources optimisées
  const imageSources = React.useMemo(() => {
    return generateImageSources(src, sizes);
  }, [src, sizes]);

  // Sélectionner la meilleure source supportée
  const selectBestSource = useCallback(() => {
    const bestFormat =
      supportedFormats.find((format) => SUPPORTED_FORMATS.includes(format)) ||
      FALLBACK_FORMAT;

    const bestSource = imageSources.find(
      (source) => source.type === `image/${bestFormat}`,
    );

    return bestSource?.src || src;
  }, [supportedFormats, imageSources, src]);

  // Charger l'image
  const loadImage = useCallback(() => {
    if (isLoaded || hasError) return;

    const imageSrc = selectBestSource();
    setCurrentSrc(imageSrc);

    const img = new Image();
    img.onload = () => {
      setIsLoaded(true);
      onLoad?.();
    };
    img.onerror = () => {
      setHasError(true);
      onError?.();
    };
    img.src = imageSrc;
  }, [isLoaded, hasError, selectBestSource, onLoad, onError]);

  // Charger l'image quand elle devient visible ou si priorité
  useEffect(() => {
    if (priority || isIntersecting) {
      loadImage();
    }
  }, [priority, isIntersecting, loadImage]);

  // Gestion des erreurs de chargement
  const handleImageError = useCallback(() => {
    setHasError(true);
    onError?.();
  }, [onError]);

  // Gestion du chargement réussi
  const handleImageLoad = useCallback(() => {
    setIsLoaded(true);
    onLoad?.();
  }, [onLoad]);

  // Rendu du fallback en cas d'erreur
  if (hasError) {
    return (
      fallback || (
        <div
          className={`bg-gray-200 flex items-center justify-center ${className}`}
          style={{ width, height }}
        >
          <span className="text-gray-400 text-sm">Image non disponible</span>
        </div>
      )
    );
  }

  // Rendu du placeholder pendant le chargement
  if (!isLoaded && !priority) {
    return (
      <div
        ref={intersectionRef}
        className={`relative ${className}`}
        style={{ width, height }}
      >
        <BlurPlaceholder
          blurDataURL={blurDataURL}
          width={width}
          height={height}
          className="absolute inset-0"
        />
        {placeholder && (
          <div className="absolute inset-0 flex items-center justify-center">
            {placeholder}
          </div>
        )}
      </div>
    );
  }

  // Rendu de l'image optimisée
  return (
    <picture className={className}>
      {/* Sources pour différents formats */}
      {imageSources.map((source, index) => (
        <source
          key={index}
          srcSet={source.src}
          type={source.type}
          sizes={source.sizes}
        />
      ))}

      {/* Image principale */}
      <img
        ref={imgRef}
        src={currentSrc || src}
        alt={alt}
        width={width}
        height={height}
        className={`transition-opacity duration-300 ${
          isLoaded ? 'opacity-100' : 'opacity-0'
        } ${className}`}
        onLoad={handleImageLoad}
        onError={handleImageError}
        loading={priority ? 'eager' : 'lazy'}
        decoding="async"
        style={{
          width,
          height,
        }}
      />
    </picture>
  );
}

// Hook pour preloader des images
export function useImagePreloader() {
  const preloadImage = useCallback((src: string) => {
    const img = new Image();
    img.src = src;
    return new Promise((resolve, reject) => {
      img.onload = () => resolve(img);
      img.onerror = reject;
    });
  }, []);

  const preloadImages = useCallback(
    async (srcs: string[]) => {
      const promises = srcs.map((src) => preloadImage(src));
      return Promise.allSettled(promises);
    },
    [preloadImage],
  );

  return { preloadImage, preloadImages };
}

// Composant pour les images responsives avec srcset
export function ResponsiveImage({
  src,
  alt,
  className = '',
  sizes = '(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw',
  ...props
}: OptimizedImageProps & { sizes?: string }) {
  return (
    <OptimizedImage
      {...props}
      src={src}
      alt={alt}
      className={className}
      sizes={sizes}
      onLoad={() => {}}
    />
  );
}
