/**
 * Vue 组件安全事件处理工具
 * 防止组件卸载时的事件处理错误
 */

/**
 * 创建安全的 Vue 组件混入，用于管理事件监听器
 * @returns {Object} Vue mixin 对象
 */
export function createSafeEventMixin() {
  return {
    data() {
      return {
        _isDestroying: false,
        _eventCleanupFunctions: []
      }
    },

    methods: {
      /**
       * 安全地注册事件监听器
       * @param {Function} registerFn - 注册事件的函数，返回清理函数
       * @returns {Function} 清理函数
       */
      $safeOn(registerFn) {
        if (this._isDestroying) return () => {}

        try {
          const cleanup = registerFn()
          if (typeof cleanup === 'function') {
            this._eventCleanupFunctions.push(cleanup)
            return cleanup
          }
        } catch (error) {
          console.error('事件注册失败:', error)
        }

        return () => {}
      },

      /**
       * 创建安全的事件处理器
       * @param {Function} handler - 原始事件处理器
       * @returns {Function} 安全的事件处理器
       */
      $safeHandler(handler) {
        return (...args) => {
          if (this._isDestroying || !this.$el) return

          try {
            return handler.apply(this, args)
          } catch (error) {
            console.error('事件处理失败:', error)
          }
        }
      },

      /**
       * 安全地执行 DOM 操作
       * @param {Function} domOperation - DOM 操作函数
       */
      $safeDom(domOperation) {
        if (this._isDestroying || !this.$el) return

        try {
          requestAnimationFrame(() => {
            if (!this._isDestroying && this.$el) {
              domOperation()
            }
          })
        } catch (error) {
          console.error('DOM 操作失败:', error)
        }
      },

      /**
       * 清理所有事件监听器
       */
      $cleanupEvents() {
        this._isDestroying = true

        this._eventCleanupFunctions.forEach(cleanup => {
          try {
            if (typeof cleanup === 'function') {
              cleanup()
            }
          } catch (error) {
            console.warn('事件清理失败:', error)
          }
        })

        this._eventCleanupFunctions = []
      }
    },

    beforeUnmount() {
      this.$cleanupEvents()
    }
  }
}

/**
 * Socket 事件安全处理混入
 */
export const socketEventMixin = {
  ...createSafeEventMixin(),

  methods: {
    /**
     * 安全地注册 socket 事件监听器
     * @param {string} event - 事件名
     * @param {Function} handler - 事件处理器
     * @returns {Function} 清理函数
     */
    $socketOn(event, handler) {
      return this.$safeOn(() => {
        const { on } = require('@/utils/socketClient')
        return on(event, this.$safeHandler(handler))
      })
    }
  }
}

/**
 * 为现有组件添加安全事件处理
 * @param {Object} component - Vue 组件选项
 * @returns {Object} 增强后的组件选项
 */
export function withSafeEvents(component) {
  const safeMixin = createSafeEventMixin()

  return {
    ...component,
    mixins: [...(component.mixins || []), safeMixin],

    // 增强现有的 beforeUnmount
    beforeUnmount() {
      // 调用原有的 beforeUnmount
      if (component.beforeUnmount) {
        try {
          component.beforeUnmount.call(this)
        } catch (error) {
          console.error('原 beforeUnmount 执行失败:', error)
        }
      }

      // 调用安全清理
      if (this.$cleanupEvents) {
        this.$cleanupEvents()
      }
    }
  }
}

/**
 * Composition API 版本的安全事件处理
 */
export function useSafeEvents() {
  const { ref, onBeforeUnmount } = require('vue')

  const isDestroying = ref(false)
  const cleanupFunctions = ref([])

  const safeOn = (registerFn) => {
    if (isDestroying.value) return () => {}

    try {
      const cleanup = registerFn()
      if (typeof cleanup === 'function') {
        cleanupFunctions.value.push(cleanup)
        return cleanup
      }
    } catch (error) {
      console.error('事件注册失败:', error)
    }

    return () => {}
  }

  const safeHandler = (handler) => {
    return (...args) => {
      if (isDestroying.value) return

      try {
        return handler(...args)
      } catch (error) {
        console.error('事件处理失败:', error)
      }
    }
  }

  const safeDom = (domOperation) => {
    if (isDestroying.value) return

    try {
      requestAnimationFrame(() => {
        if (!isDestroying.value) {
          domOperation()
        }
      })
    } catch (error) {
      console.error('DOM 操作失败:', error)
    }
  }

  const cleanup = () => {
    isDestroying.value = true

    cleanupFunctions.value.forEach(fn => {
      try {
        if (typeof fn === 'function') {
          fn()
        }
      } catch (error) {
        console.warn('事件清理失败:', error)
      }
    })

    cleanupFunctions.value = []
  }

  onBeforeUnmount(() => {
    cleanup()
  })

  return {
    isDestroying: isDestroying.value,
    safeOn,
    safeHandler,
    safeDom,
    cleanup
  }
}

export default {
  createSafeEventMixin,
  socketEventMixin,
  withSafeEvents,
  useSafeEvents
}
