import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import type { RouteLocationNormalizedLoaded } from 'vue-router'

import { fetchAdminNotificationUnreadCount } from '@/features/admin/api/adminNotifications'
import { useAdminSessionStore } from '@/stores/adminSession'

export const adminNotificationUnreadChangedEvent = 'admin-notification-unread-changed'

export function useAdminNotificationUnreadCount(route: RouteLocationNormalizedLoaded) {
  const adminSession = useAdminSessionStore()
  const unreadCount = ref(0)
  let timer: number | null = null
  let requestID = 0

  const unreadLabel = computed(() => (unreadCount.value > 99 ? '99+' : String(unreadCount.value)))

  function stopPolling() {
    if (timer) {
      window.clearInterval(timer)
      timer = null
    }
  }

  async function loadUnreadCount() {
    if (!adminSession.hasSessionHint) {
      unreadCount.value = 0
      return
    }

    const currentID = ++requestID
    try {
      const count = await fetchAdminNotificationUnreadCount()
      if (currentID === requestID) {
        unreadCount.value = count
      }
    } catch {
      // 后台角标静默失败，避免干扰当前操作。
    }
  }

  function startPolling() {
    stopPolling()
    void loadUnreadCount()
    timer = window.setInterval(loadUnreadCount, 30_000)
  }

  function resumePollingIfVisible() {
    if (document.hidden || !adminSession.hasSessionHint) return
    startPolling()
  }

  function handleVisibilityChange() {
    if (document.hidden) {
      stopPolling()
      return
    }
    resumePollingIfVisible()
  }

  function handleUnreadChanged() {
    void loadUnreadCount()
  }

  onMounted(() => {
    window.addEventListener(adminNotificationUnreadChangedEvent, handleUnreadChanged)
    document.addEventListener('visibilitychange', handleVisibilityChange)
    resumePollingIfVisible()
  })

  onBeforeUnmount(() => {
    stopPolling()
    window.removeEventListener(adminNotificationUnreadChangedEvent, handleUnreadChanged)
    document.removeEventListener('visibilitychange', handleVisibilityChange)
  })

  watch(
    () => adminSession.hasSessionHint,
    hasSession => {
      if (hasSession) {
        resumePollingIfVisible()
        return
      }
      stopPolling()
      unreadCount.value = 0
    }
  )

  watch(
    () => route.fullPath,
    () => {
      void loadUnreadCount()
    }
  )

  return {
    unreadCount,
    unreadLabel,
    refreshUnreadCount: loadUnreadCount,
  }
}
