import React from 'react';
import { Image, ImageProps, StyleSheet, Text, View } from 'react-native';
import {
  DEFAULT_PLANT_IMAGE_URI,
  getCategoryFallbackImage,
  getPlantImageSourceFallbackUri,
  getWikimediaFilePathFromThumbnailUrl,
  resolveImageUri,
  tryResolveImageUri,
} from '../utils/imageUri';

type SafeImageFallbackMode = 'category' | 'default' | 'none';

interface SafeImageProps extends Omit<ImageProps, 'source'> {
  uri?: string | null;
  categories?: string[];
  fallbackMode?: SafeImageFallbackMode;
  placeholderLabel?: string;
}

const getPlaceholderInitial = (label?: string): string => {
  if (!label) return '?';
  const trimmed = label.trim();
  if (!trimmed) return '?';
  return trimmed.charAt(0).toUpperCase();
};

export const SafeImage: React.FC<SafeImageProps> = ({
  uri,
  categories,
  fallbackMode = 'category',
  placeholderLabel,
  onError,
  style,
  ...props
}) => {
  const categoryFallback = categories && categories.length > 0
    ? getCategoryFallbackImage(categories)
    : DEFAULT_PLANT_IMAGE_URI;
  const selectedFallback = fallbackMode === 'category'
    ? categoryFallback
    : DEFAULT_PLANT_IMAGE_URI;

  const [resolvedUri, setResolvedUri] = React.useState<string>(() => {
    const strictResolved = tryResolveImageUri(uri);
    if (strictResolved) return strictResolved;
    return fallbackMode === 'none' ? '' : selectedFallback;
  });
  const [showPlaceholder, setShowPlaceholder] = React.useState<boolean>(() => {
    if (fallbackMode !== 'none') return false;
    return !tryResolveImageUri(uri);
  });
  const [retryCount, setRetryCount] = React.useState(0);
  const lastAttemptUri = React.useRef<string | null>(null);

  React.useEffect(() => {
    const strictResolved = tryResolveImageUri(uri);
    setResolvedUri(strictResolved || (fallbackMode === 'none' ? '' : selectedFallback));
    setShowPlaceholder(fallbackMode === 'none' && !strictResolved);
    setRetryCount(0);
    lastAttemptUri.current = strictResolved;
  }, [uri, fallbackMode, selectedFallback]);

  if (fallbackMode === 'none' && showPlaceholder) {
    return (
      <View style={[styles.placeholder, style]}>
        <Text style={styles.placeholderText}>{getPlaceholderInitial(placeholderLabel)}</Text>
      </View>
    );
  }

  return (
    <Image
      {...props}
      style={style}
      source={{
        uri: resolvedUri || selectedFallback
      }}
      onError={(event) => {
        onError?.(event);

        const currentUri = resolvedUri || selectedFallback;

        // Smart Retry Logic for Wikimedia (first failure only)
        if (retryCount === 0 && currentUri.includes('upload.wikimedia.org')) {
          const fileName = getWikimediaFilePathFromThumbnailUrl(currentUri);
          if (fileName) {
            const redirectUrl = `https://commons.wikimedia.org/wiki/Special:FilePath/${encodeURIComponent(fileName)}`;
            setRetryCount(1);
            setResolvedUri(redirectUrl);
            lastAttemptUri.current = redirectUrl;
            return;
          }
        }

        const sourceFallbackUri = getPlantImageSourceFallbackUri(uri);
        if (sourceFallbackUri && sourceFallbackUri !== currentUri && lastAttemptUri.current !== sourceFallbackUri) {
          setResolvedUri(sourceFallbackUri);
          lastAttemptUri.current = sourceFallbackUri;
          return;
        }

        // If we get here, either it wasn't a Wikimedia URL, or filename extraction failed,
        // or the retry itself failed.
        if (fallbackMode === 'none') {
          setShowPlaceholder(true);
          return;
        }

        setResolvedUri((current) => {
          if (current === DEFAULT_PLANT_IMAGE_URI) return current;
          if (current === selectedFallback) return DEFAULT_PLANT_IMAGE_URI;
          return selectedFallback;
        });

        // Prevent infinite loops if fallbacks also fail
        setRetryCount(current => current + 1);
      }}
    />
  );
};

const styles = StyleSheet.create({
  placeholder: {
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: '#e7ece8',
  },
  placeholderText: {
    fontSize: 18,
    fontWeight: '700',
    color: '#5f6f63',
  },
});
