import React, { forwardRef, memo, useEffect, useMemo, useState } from 'react'
import { Image as ExpoImage, ImageProps as ExpoImageProps } from 'expo-image'
import { TouchableOpacity, TouchableOpacityProps, View } from 'react-native'

interface ImgProps extends ExpoImageProps {
  onClick?: () => void
  touchProps?: TouchableOpacityProps
  className?: string
  src?: string | number
  errorSource?: string | number
  /** 图片宽度，用于 CDN 压缩 */
  width?: number
  /** 是否使用 WebP 格式（默认 true） */
  isWebP?: boolean
  /** 是否启用 CDN 压缩（默认 false） */
  isCompression?: boolean
  /** 自定义缓存键，用于需要重定向的 URL */
  cacheKey?: string
  /** 占位图 URL，在真实图片加载完成前显示 */
  placeholderSrc?: string
}

const Img = forwardRef<ExpoImage, ImgProps>((props, ref) => {
  const {
    onClick,
    touchProps = {},
    className = '',
    style,
    src,
    errorSource,
    source: propSource,
    width = 256,
    isWebP = true,
    isCompression = false,
    cacheKey,
    placeholderSrc,
    onLoad,
    ...reset
  } = props

  const [isLoaded, setIsLoaded] = useState(false)

  useEffect(() => {
    setIsLoaded(false)
  }, [src])

  // 判断是否为网络图片
  const isNetworkImage = (uri: string | number): boolean => {
    if (typeof uri === 'number') return false
    return uri.startsWith('http://') || uri.startsWith('https://')
  }

  // CDN 压缩 URL（使用 Cloudflare 图片优化服务）
  const compressionUrl = useMemo((): string | undefined => {
    if (!src || typeof src !== 'string' || !isNetworkImage(src)) return undefined
    const format = isWebP ? 'webp' : 'jpg'
    return `https://bowong.cc/cdn-cgi/image/width=${width},quality=75,format=${format}/${src}`
  }, [width, isWebP, src])

  // 构建图片源
  const imageSource = useMemo(() => {
    // 如果提供了source属性，优先使用
    if (propSource) return propSource

    if (!src) return undefined

    if (typeof src === 'number') {
      // 本地图片资源（require导入的资源ID）
      return src
    } else {
      // 网络图片或本地文件路径
      if (isNetworkImage(src)) {
        const finalUrl = (isCompression && compressionUrl) ? compressionUrl : src
        return {
          uri: finalUrl,
          cacheKey: cacheKey || finalUrl,
        }
      } else {
        // 本地文件路径
        return { uri: src }
      }
    }
  }, [src, propSource, cacheKey, isCompression, compressionUrl])

  const handleLoad = (e: any) => {
    setIsLoaded(true)
    onLoad?.(e)
  }

  const handlePress = () => {
    onClick && onClick()
  }

  // 渲染图片内容
  const renderImage = () => {
    // 无占位图时直接返回原图
    if (!placeholderSrc) {
      return (
        <ExpoImage
          ref={ref}
          style={style}
          source={imageSource}
          cachePolicy="disk"
          recyclingKey={typeof src === 'string' ? src : undefined}
          transition={{ duration: 200, effect: 'cross-dissolve' }}
          onLoad={onLoad}
          {...reset}
        />
      )
    }

    // 有占位图时使用层叠布局
    return (
      <View style={[style, { overflow: 'hidden' }]}>
        {/* 占位图层 - 加载完成后隐藏 */}
        <ExpoImage
          style={{ position: 'absolute', width: '100%', height: '100%' }}
          source={{ uri: placeholderSrc }}
          cachePolicy="disk"
          contentFit={reset.contentFit || 'cover'}
          transition={{ duration: 100, effect: 'curl-up' }}
        />

        {/* 真实图片层 */}
        <ExpoImage
          ref={ref}
          style={{ width: '100%', height: '100%', opacity: isLoaded ? 1 : 0 }}
          source={imageSource}
          cachePolicy="disk"
          recyclingKey={typeof src === 'string' ? src : undefined}
          transition={{ duration: 300, effect: 'cross-dissolve' }}
          onLoad={handleLoad}
          contentFit={reset.contentFit || 'cover'}
          {...reset}
        />
      </View>
    )
  }

  if (onClick) {
    return (
      <TouchableOpacity onPress={handlePress} {...touchProps}>
        {renderImage()}
      </TouchableOpacity>
    )
  }

  return renderImage()
})

Img.displayName = 'Img'
export default memo(Img)
