/**
 * SmartImage 智能图片组件
 * 支持加载状态、错误处理、自适应尺寸
 * 基于 expo-image 封装，原生支持 GIF/WebP 动图
 */

import React, { useState, useCallback, useRef, useEffect, useMemo } from 'react';
import {
  View,
  StyleSheet,
  ViewStyle,
  ImageStyle,
  ActivityIndicator,
  Pressable,
  StyleProp,
  Platform,
} from 'react-native';
import { Image as ExpoImage } from 'expo-image';
import { MaterialCommunityIcons } from '@expo/vector-icons';
import { borderRadius, useAppColors, type AppColors } from '../../theme';

function createSmartImageStyles(colors: AppColors) {
  return StyleSheet.create({
    image: {
      flex: 1,
      width: '100%',
      height: '100%',
    },
    variantImage: {
      flex: 1,
    },
    overlay: {
      ...StyleSheet.absoluteFillObject,
      justifyContent: 'center',
      alignItems: 'center',
      backgroundColor: colors.background.disabled,
    },
    loadingContainer: {
      padding: 8,
      borderRadius: borderRadius.md,
      backgroundColor: `${colors.background.paper}E6`,
    },
    errorContainer: {
      padding: 12,
      borderRadius: borderRadius.md,
      backgroundColor: `${colors.text.primary}0D`,
    },
  });
}

// 图片加载状态
export type ImageLoadState = 'loading' | 'success' | 'error';

// 图片源类型 - 兼容多种数据格式
export interface ImageSource {
  uri?: string;
  url?: string;
  width?: number;
  height?: number;
}

// SmartImage Props
export interface SmartImageProps {
  /** 图片源 */
  source: ImageSource | string;
  /** 容器样式 */
  style?: StyleProp<ViewStyle>;
  /** 图片样式 */
  imageStyle?: StyleProp<ImageStyle>;
  /** 图片填充模式 */
  resizeMode?: 'cover' | 'contain' | 'stretch' | 'repeat' | 'center';
  /** 是否显示加载指示器 */
  showLoading?: boolean;
  /** 是否显示错误占位图 */
  showError?: boolean;
  /** 圆角大小 */
  borderRadius?: number;
  /** 点击回调 */
  onPress?: () => void;
  /** 长按回调 */
  onLongPress?: () => void;
  /** 加载完成回调 */
  onLoad?: () => void;
  /** 加载失败回调 */
  onError?: (error: any) => void;
  /** 测试ID */
  testID?: string;
  /** 预览图 URL */
  previewUrl?: string;
  /** 是否使用预览图（优先加载预览图） */
  usePreview?: boolean;
  /** 是否懒加载 */
  lazyLoad?: boolean;
  /** Web 端 IntersectionObserver rootMargin，略提前加载进入视口附近的图 */
  lazyRootMargin?: string;
  /** 缓存策略 */
  cachePolicy?: 'memory' | 'disk' | 'memory-disk' | 'none';
}

/**
 * 智能图片组件
 * 自动处理加载状态、错误状态
 */
export const SmartImage: React.FC<SmartImageProps> = ({
  source,
  style,
  imageStyle,
  resizeMode = 'cover',
  showLoading = true,
  showError = true,
  borderRadius: borderRadiusValue = 0,
  onPress,
  onLongPress,
  onLoad,
  onError,
  testID,
  previewUrl,
  usePreview = false,
  lazyLoad = false,
  lazyRootMargin = '160px',
  cachePolicy = 'memory-disk',
}) => {
  const colors = useAppColors();
  const styles = useMemo(() => createSmartImageStyles(colors), [colors]);
  const [loadState, setLoadState] = useState<ImageLoadState>('loading');
  const [isVisible, setIsVisible] = useState(() => !lazyLoad || Platform.OS !== 'web');
  const [shouldLoadOriginal, setShouldLoadOriginal] = useState(false);
  const lazyTargetRef = useRef<View>(null);

  // 解析图片源 - 支持 uri 或 url 字段
  const imageUri = typeof source === 'string'
    ? source
    : (source.uri || source.url || '');

  // 解析预览图 URL
  const previewUri = typeof previewUrl === 'string' ? previewUrl : '';

  useEffect(() => {
    setShouldLoadOriginal(false);
    setLoadState('loading');
  }, [imageUri]);

  useEffect(() => {
    if (!lazyLoad) {
      setIsVisible(true);
      return;
    }
    if (Platform.OS !== 'web') {
      setIsVisible(true);
      return;
    }
    setIsVisible(false);
    const node = lazyTargetRef.current as unknown as Element | null;
    if (!node || typeof IntersectionObserver === 'undefined') {
      setIsVisible(true);
      return;
    }
    const observer = new IntersectionObserver(
      entries => {
        if (entries.some(e => e.isIntersecting)) {
          setIsVisible(true);
          observer.disconnect();
        }
      },
      { rootMargin: lazyRootMargin }
    );
    observer.observe(node);
    return () => observer.disconnect();
  }, [lazyLoad, lazyRootMargin, imageUri]);

  // 智能选择图片 URL
  const getImageUrl = useCallback((): string => {
    // 如果应该加载原图（预览图已加载完成或没有预览图）
    if (shouldLoadOriginal || !usePreview || !previewUri) {
      return imageUri;
    }
    // 否则使用预览图
    return previewUri;
  }, [imageUri, previewUri, usePreview, shouldLoadOriginal]);

  // 处理加载开始
  const handleLoadStart = useCallback(() => {
    setLoadState('loading');
  }, []);

  // 处理加载完成
  const handleLoad = useCallback(() => {
    setLoadState('success');
    // 如果正在加载预览图，切换到原图
    if (usePreview && !shouldLoadOriginal && previewUri && getImageUrl() === previewUri) {
      setShouldLoadOriginal(true);
    }
    onLoad?.();
  }, [onLoad, usePreview, shouldLoadOriginal, previewUri, getImageUrl]);

  // 处理加载错误
  const handleError = useCallback(
    (error: any) => {
      // 如果预览图加载失败，尝试加载原图
      if (usePreview && !shouldLoadOriginal && getImageUrl() === previewUri && imageUri) {
        setShouldLoadOriginal(true);
        return;
      }
      setLoadState('error');
      onError?.(error);
    },
    [onError, usePreview, shouldLoadOriginal, getImageUrl, previewUri, imageUri]
  );

  // 重试加载
  const handleRetry = useCallback(() => {
    setLoadState('loading');
  }, []);

  // 渲染加载指示器
  const renderLoading = () => {
    if (!showLoading || loadState !== 'loading') return null;

    return (
      <View style={styles.overlay}>
        <View style={styles.loadingContainer}>
          <ActivityIndicator size="small" color={colors.primary.main} />
        </View>
      </View>
    );
  };

  // 渲染错误占位图
  const renderError = () => {
    if (!showError || loadState !== 'error') return null;

    return (
      <Pressable style={styles.overlay} onPress={handleRetry}>
        <View style={styles.errorContainer}>
          <MaterialCommunityIcons
            name="image-off-outline"
            size={24}
            color={colors.text.hint}
          />
        </View>
      </Pressable>
    );
  };

  // 容器样式
  const containerStyle: ViewStyle = {
    borderRadius: borderRadiusValue,
    overflow: 'hidden',
  };

  // 图片源配置
  const imageSource = imageUri && imageUri.trim() !== '' ? { uri: getImageUrl() } : undefined;

  // 如果没有有效的图片源，显示错误占位
  if (!imageSource) {
    return (
      <Pressable
        style={[containerStyle, style as ViewStyle, { backgroundColor: colors.background.disabled }]}
        testID={testID}
      >
        <View style={styles.errorContainer}>
          <MaterialCommunityIcons
            name="image-off-outline"
            size={24}
            color={colors.text.hint}
          />
        </View>
      </Pressable>
    );
  }

  // 如果是懒加载且不可见，显示占位（Web 上由 IntersectionObserver 驱动进入视口后再加载）
  if (lazyLoad && !isVisible) {
    return (
      <View
        ref={Platform.OS === 'web' ? lazyTargetRef : undefined}
        collapsable={false}
        style={[containerStyle, style as ViewStyle, { backgroundColor: colors.background.default }]}
        testID={testID}
      />
    );
  }

  return (
    <Pressable
      style={[containerStyle, style as ViewStyle]}
      onPress={onPress}
      onLongPress={onLongPress}
      disabled={!onPress && !onLongPress}
      testID={testID}
    >
      <ExpoImage
        source={imageSource}
        style={[styles.image, imageStyle as ImageStyle]}
        contentFit={
          resizeMode === 'stretch' ? 'fill' :
          resizeMode === 'repeat' ? 'cover' :
          resizeMode === 'center' ? 'scale-down' :
          resizeMode
        }
        cachePolicy={cachePolicy}
        onLoadStart={handleLoadStart}
        onLoad={handleLoad}
        onError={handleError}
      />
      {renderLoading()}
      {renderError()}
    </Pressable>
  );
};

// 预定义尺寸变体
export interface ImageVariantProps extends Omit<SmartImageProps, 'style'> {
  /** 尺寸变体 */
  variant?: 'thumbnail' | 'small' | 'medium' | 'large' | 'full';
  /** 自定义尺寸 */
  size?: number;
  /** 宽高比 */
  aspectRatio?: number;
}

/**
 * 变体图片组件
 * 提供预定义的尺寸变体
 */
export const VariantImage: React.FC<ImageVariantProps> = ({
  variant = 'medium',
  size,
  aspectRatio,
  imageStyle,
  ...props
}) => {
  const getVariantStyle = (): ViewStyle => {
    switch (variant) {
      case 'thumbnail':
        return { width: size || 40, height: size || 40 };
      case 'small':
        return { width: size || 80, height: size || 80 };
      case 'medium':
        return { width: size || 120, height: size || 120 };
      case 'large':
        return { width: size || 200, height: size || 200 };
      case 'full':
        return { flex: 1 };
      default:
        return { width: size || 120, height: size || 120 };
    }
  };

  const variantStyle = getVariantStyle();

  // 如果有宽高比，调整高度
  const finalStyle: ViewStyle = { ...variantStyle };
  if (aspectRatio && finalStyle.width && !size) {
    finalStyle.height = (finalStyle.width as number) / aspectRatio;
  }

  return (
    <SmartImage
      {...props}
      style={finalStyle}
      imageStyle={[variantStyles.variantImage, imageStyle]}
    />
  );
};

const variantStyles = StyleSheet.create({
  variantImage: {
    flex: 1,
  },
});

export default SmartImage;
