/**
 * 全局输入表情符号拦截守卫（极简，无侵入）
 * 作用：拦截所有原生 input/textarea 的输入事件，移除 Emoji，并重新派发 input 事件以同步 v-model
 * 注意：
 * - 跳过正在输入法合成阶段（compositionstart ~ compositionend），避免影响中文输入
 * - 默认对所有可编辑 input/textarea 生效；如需个别放行，可在元素上加 data-allow-emoji="true"
 */
export const initNoEmojiGuard = () => {
  if (typeof window === 'undefined') return
  if (window.__noEmojiGuardInitialized) return
  window.__noEmojiGuardInitialized = true

  // 覆盖常见 Emoji、旗帜、杂项符号、ZWJ、变体选择符、组合键帽
  const emojiPattern = /[\u{1F300}-\u{1FAFF}]|[\u{1F1E6}-\u{1F1FF}]|[\u{2600}-\u{26FF}]|[\u{2700}-\u{27BF}]|[\u{FE0F}]|[\u{200D}]|[\u{20E3}]/gu

  /**
   * 判断是否是需要拦截的可编辑元素
   * @param {EventTarget} el 事件目标
   * @returns {boolean}
   */
  const isEditableTarget = (el) => {
    if (!el || !(el instanceof Element)) return false
    if (el.getAttribute && el.getAttribute('data-allow-emoji') === 'true') return false
    const tag = el.tagName
    if (tag === 'INPUT') {
      const type = (el.getAttribute('type') || 'text').toLowerCase()
      // 排除不会产生文本的类型
      const disallow = ['checkbox', 'radio', 'file', 'hidden', 'button', 'submit', 'reset', 'range', 'color', 'date', 'datetime-local', 'month', 'time', 'week']
      return disallow.indexOf(type) === -1
    }
    if (tag === 'TEXTAREA') return true
    return false
  }

  // 记录输入法合成状态
  const setComposing = (el, composing) => {
    try { el.__noEmojiComposing = composing } catch (e) {}
  }
  const isComposing = (el) => !!(el && el.__noEmojiComposing)

  // 结束合成时做一次清洗
  document.addEventListener('compositionstart', (e) => {
    if (!isEditableTarget(e.target)) return
    setComposing(e.target, true)
  }, true)
  document.addEventListener('compositionend', (e) => {
    if (!isEditableTarget(e.target)) return
    setComposing(e.target, false)
    sanitizeAndRedispatch(e.target)
  }, true)

  // 主输入拦截：捕获阶段尽早处理
  document.addEventListener('input', (e) => {
    const target = e.target
    if (!isEditableTarget(target)) return
    if (isComposing(target)) return
    sanitizeAndRedispatch(target)
  }, true)

  /**
   * 清洗目标元素的值并在变更时重新派发 input 事件
   * @param {HTMLInputElement|HTMLTextAreaElement} target
   */
  function sanitizeAndRedispatch(target) {
    const before = String(target.value ?? '')
    if (!before) return
    if (!emojiPattern.test(before)) return
    const selectionStart = target.selectionStart
    const selectionEnd = target.selectionEnd
    const after = before.replace(emojiPattern, '')
    if (after === before) return
    target.value = after
    try {
      // 重置光标，尽量贴近原位置
      if (typeof selectionStart === 'number' && typeof selectionEnd === 'number') {
        const removed = before.length - after.length
        const nextPos = Math.max(0, selectionStart - removed)
        target.setSelectionRange(nextPos, nextPos)
      }
    } catch (e) {}
    // 重新派发 input 事件以同步 v-model
    const evt = new Event('input', { bubbles: true })
    target.dispatchEvent(evt)
  }
}


