import { Image as ExpoImage, type ImageRef } from 'expo-image'
import { memo, useEffect, useRef, useState } from 'react'
import { View, type ViewStyle } from 'react-native'
import Video from 'react-native-video'
import tw from 'twrnc'

import { videoUrlCache } from '@/utils/storage'
import { mp4ToWebpUrl } from '@/utils/uploadFile'

import Img from './Img'

type Props = {
  className?: string
  url?: string
  placeholderUrl?: string
  needWeb?: boolean
  style?: ViewStyle
  width?: number
  autoplay?: boolean // 控制动画播放，默认 true
} & React.ComponentProps<typeof Video>

// videoUrlCache.clear()
// ExpoImage.clearDiskCache()
// ExpoImage.clearMemoryCache()
// 默认宽度256半屏宽度
const VideoBox = ({
  className = '',
  url,
  placeholderUrl = '',
  width = 256,
  style,
  autoplay = true,
  ...videoProps
}: Props) => {
  const [urlFinal, setUrlFinal] = useState('')
  const imageRef = useRef<ImageRef | null>(null)

  const isImg = (url: any) => {
    if (!url) return false
    const lowerUrl = url.toLowerCase()
    return lowerUrl?.match(/\.(jpg|jpeg|png|gif|webp|bmp|tiff|svg)(\?.*)?$/i)
  }

  // / 本地文件全部用video组件播放
  const isLocal = !url.startsWith('http://') && !url.startsWith('https://')
  const isImageFile = isImg(url)

  const setRedirectUrl = async (isCancelled: () => boolean, url?: string) => {
    const isImg2 = isImg(url)
    if (isImg2) {
      if (!isCancelled()) {
        setUrlFinal(url!)
      }
      return
    }

    try {
      // 先尝试从缓存获取
      const cachedUrl = await videoUrlCache.get(url!, width)
      // console.log('getRedirectUrl cachedUrl-----------', url, cachedUrl, width)
      if (cachedUrl) {
        // 只有当请求未被取消时才更新状态
        if (!isCancelled()) {
          setUrlFinal(cachedUrl)
        }
        return
      }

      const webpUrl = await mp4ToWebpUrl({ videoUrl: url!, width, height: width })

      // 只有当请求未被取消时才缓存和更新状态
      if (!isCancelled()) {
        // 缓存结果
        await videoUrlCache.set(url!, webpUrl, width)

        // console.log('setRedirectUrl finalUrl-----------', finalUrl)
        setUrlFinal(webpUrl)
      }
    } catch (error) {
      console.warn('获取视频URL失败:', error)
      // 只有当请求未被取消时才更新状态
      if (!isCancelled()) {
        // 错误时尝试使用原始URL
        setUrlFinal(url!)
      }
    }
  }

  useEffect(() => {
    // 每次url变化强制刷新
    setUrlFinal('')
    if (!url || isLocal) {
      return
    }

    // 用于标记当前请求是否已过期
    let cancelled = false

    setTimeout(() => {
      if (!cancelled) {
        setRedirectUrl(() => cancelled, url)
      }
    }, 0)

    // 清理函数：当 url 变化或组件卸载时，标记当前请求为已取消
    return () => {
      cancelled = true
    }
  }, [url, width])

  // 控制动画播放/停止
  useEffect(() => {
    // 添加延迟和安全检查，确保 ref 已就绪且组件未卸载
    const timer = setTimeout(() => {
      try {
        if (imageRef?.current) {
          if (autoplay) {
            imageRef.current?.startAnimating()
          } else {
            imageRef.current?.stopAnimating()
          }
        }
      } catch (error) {
        // 忽略动画控制错误，避免崩溃
        console.debug('Animation control failed:', error)
      }
    }, 100)

    return () => clearTimeout(timer)
  }, [autoplay, urlFinal])

  if (!url) return null

  if (isLocal) {
    if (!isImageFile) {
      return (
        <Video
          key={url ?? 'no-url'}
          muted
          repeat
          controls={false}
          paused={false}
          poster={url}
          resizeMode="cover"
          source={{ uri: url }}
          style={style as any}
          viewType={0}
          volume={0}
          {...videoProps}
        />
      )
    }
    return (
      <ExpoImage
        cachePolicy="disk"
        source={{ uri: url }}
        style={style as any}
        transition={{ duration: 200, effect: 'cross-dissolve' }}
      />
    )
  }

  const imageStyle = tw`${className}`

  const showPlaceholder = !!placeholderUrl

  return (
    <View style={[style, imageStyle, { overflow: 'hidden' }]}>
      {/* 占位图层 - 加载完成后隐藏 */}
      {showPlaceholder && (
        <Img
          isCompression={false}
          isWebP={true}
          src={placeholderUrl}
          style={{ position: 'absolute', width: '100%', height: '100%' }}
          contentFit={'cover'}
          transition={{ duration: 100, effect: 'curl-up' }}
        />
      )}

      {/* 真实图片层 */}
      <ExpoImage
        ref={imageRef}
        // iOS 优化：使用 memory-disk 策略，但设置较低的内存缓存优先级
        cachePolicy="disk"
        // 添加 recyclingKey 帮助内存回收
        recyclingKey={url}
        // iOS 性能优化：允许降采样
        allowDownscaling={true}
        // 设置解码格式（iOS 优化）
        decoding="async"
        contentFit={'cover'}
        source={{ uri: urlFinal }}
        style={style as any}
        autoplay={autoplay}
        transition={{ duration: 200, effect: 'cross-dissolve' }}
      />
    </View>
  )
}

export default memo(VideoBox)
