// src/directives/smartImage.js
import { imageCacheManager } from '@/utils/imageCacheManager'
import { nextTick } from 'vue'

export const smartImage = {
  async mounted(el, binding) {
    // 检查是否需要跳过渐变效果
    const skipFade = binding.modifiers.noFade || binding.arg === 'noFade'

    // 设置加载状态样式
    if (!skipFade) {
      el.style.opacity = '0'
      el.style.transition = 'opacity 0.3s ease-in-out'
    }

    // 获取 URL：优先使用 binding.value，如果为空则尝试从元素获取
    const url = getValidUrl(binding.value, el)

    if (url) {
      await processImage(el, url, skipFade)

      // 保存当前处理的 URL，用于后续比较
      el._smartImageCurrentUrl = url
      // 保存原始绑定值
      el._smartImageOriginalBindingValue = binding.value
    } else {
      // 如果 URL 无效，恢复透明度
      if (!skipFade) {
        el.style.opacity = '1'
      }
    }
  },

  async updated(el, binding) {
    // 检查是否需要跳过渐变效果
    const skipFade = binding.modifiers.noFade || binding.arg === 'noFade'

    // 获取当前有效的 URL
    const currentUrl = getValidUrl(binding.value, el)

    // 检查是否真的需要更新
    // 1. binding.value 发生了变化
    // 2. 或者元素的 src 属性发生了变化
    const bindingChanged = binding.value !== binding.oldValue
    const elementSrcChanged = currentUrl && currentUrl !== el._smartImageCurrentUrl

    if (bindingChanged || elementSrcChanged) {
      if (currentUrl && currentUrl !== el._smartImageCurrentUrl) {
        // 设置加载状态
        if (!skipFade) {
          el.style.opacity = '0'
        }
        await processImage(el, currentUrl, skipFade)
        el._smartImageCurrentUrl = currentUrl
        el._smartImageOriginalBindingValue = binding.value
      }
    }
  },

  // 清理函数
  unmounted(el) {
    // 清理可能的事件监听器
    el.removeEventListener('load', el._smartImageLoadHandler)
    el.removeEventListener('error', el._smartImageErrorHandler)
    // 清理保存的引用
    delete el._smartImageCurrentUrl
    delete el._smartImageOriginalBindingValue
    delete el._smartImageLoadHandler
    delete el._smartImageErrorHandler
  },
}

// 获取有效的 URL
function getValidUrl(bindingValue, el) {
  // 优先级：1. binding.value 2. el.getAttribute('src') 3. el.src
  const candidates = [bindingValue, el.getAttribute('src'), el.src]

  for (const candidate of candidates) {
    if (
      candidate &&
      candidate !== 'null' &&
      candidate !== 'undefined' &&
      !candidate.includes('blob:') &&
      typeof candidate === 'string'
    ) {
      return candidate
    }
  }

  return null
}

// 将图片处理逻辑提取为单独函数
async function processImage(el, url, skipFade = false) {
  if (!url) {
    return
  }

  await nextTick()

  try {
    // 目标符合缓存条件
    if (imageCacheManager.isBuildAsset(url)) {
      // 获取缓存的图片 URL（如果是缓存的图片会返回 blob URL，否则返回原始 URL）
      const imageUrl = await imageCacheManager.getCacheImageUrl(url)

      // 设置加载完成的回调
      const handleLoad = () => {
        if (!skipFade) {
          el.style.opacity = '1'
        }
        el.removeEventListener('load', handleLoad)
      }
      el.addEventListener('load', handleLoad)
      el._smartImageLoadHandler = handleLoad // 保存引用以便清理

      // 设置错误处理回调
      const handleError = (error) => {
        console.error(`图片加载失败:`, url, error)
        if (!skipFade) {
          el.style.opacity = '1'
        }
        el.removeEventListener('error', handleError)
      }
      el.addEventListener('error', handleError)
      el._smartImageErrorHandler = handleError // 保存引用以便清理

      // 设置图片源
      el.src = imageUrl
    } else {
      // 外部链接直接加载
      const handleLoad = () => {
        if (!skipFade) {
          el.style.opacity = '1'
        }
        el.removeEventListener('load', handleLoad)
      }
      el.addEventListener('load', handleLoad)
      el._smartImageLoadHandler = handleLoad

      const handleError = (error) => {
        // console.error(`外部图片加载失败:`, url, error)
        if (!skipFade) {
          el.style.opacity = '1'
        }
        el.removeEventListener('error', handleError)
      }
      el.addEventListener('error', handleError)
      el._smartImageErrorHandler = handleError

      el.src = url
    }
  } catch (error) {
    console.warn(`图片处理失败: ${url}`, error)
    el.src = url
    if (!skipFade) {
      el.style.opacity = '1'
    }
  }
}
