"use client"

import { useEffect, useRef, useState, useCallback } from "react"

import type { Notification } from "../types"
import {
  getNotificationsAction,
  getUnreadNotificationCountAction,
} from "../actions"

interface NotificationStreamData {
  type: "update" | "error"
  unreadCount?: number
  notifications?: Notification[]
  message?: string
}

interface UseNotificationStreamOptions {
  /** 是否启用 SSE（默认 true） */
  enabled?: boolean
  /** SSE 连接失败后的轮询降级间隔（毫秒），默认 30000 */
  fallbackPollInterval?: number
  /** 初始未读数 */
  initialUnreadCount?: number
  /** 初始通知列表 */
  initialNotifications?: Notification[]
}

interface UseNotificationStreamResult {
  /** 未读通知数 */
  unreadCount: number
  /** 最新通知列表 */
  notifications: Notification[]
  /** SSE 是否已连接 */
  isConnected: boolean
  /** 是否正在使用轮询降级模式 */
  isUsingFallback: boolean
  /** 手动刷新（轮询降级模式下使用） */
  refresh: () => void
}

/**
 * 通知实时推送 Hook
 *
 * 优先使用 SSE（Server-Sent Events）接收实时通知更新，
 * 当 SSE 不可用时自动降级为轮询模式（调用 Server Actions）。
 *
 * SSE 优势：
 * - 实时推送（延迟 < 1 秒）
 * - 低服务器负载（单连接 + 定时推送）
 * - 自动重连（浏览器原生支持）
 *
 * 降级策略：
 * - SSE 连接失败 / 浏览器不支持 EventSource → 切换为轮询模式
 * - 轮询调用 getNotificationsAction + getUnreadNotificationCountAction
 * - 轮询间隔为 fallbackPollInterval（默认 30 秒）
 */
export function useNotificationStream(options?: UseNotificationStreamOptions): UseNotificationStreamResult {
  const enabled = options?.enabled ?? true
  const fallbackPollInterval = options?.fallbackPollInterval ?? 30_000

  const [unreadCount, setUnreadCount] = useState(options?.initialUnreadCount ?? 0)
  const [notifications, setNotifications] = useState<Notification[]>(options?.initialNotifications ?? [])
  const [isConnected, setIsConnected] = useState(false)
  const [isUsingFallback, setIsUsingFallback] = useState(false)

  const eventSourceRef = useRef<EventSource | null>(null)
  const pollTimerRef = useRef<ReturnType<typeof setInterval> | null>(null)
  const pollFnRef = useRef<(() => Promise<void>) | null>(null)

  /** 通过 Server Actions 拉取一次通知数据（轮询降级模式使用） */
  const fetchOnce = useCallback(async (): Promise<void> => {
    try {
      const [countRes, listRes] = await Promise.all([
        getUnreadNotificationCountAction(),
        getNotificationsAction({ pageSize: 10 }),
      ])
      if (countRes.success && typeof countRes.data === "number") {
        setUnreadCount(countRes.data)
      }
      if (listRes.success && listRes.data) {
        setNotifications(listRes.data.items)
      }
    } catch {
      // 轮询失败静默处理
    }
  }, [])

  /** 手动刷新（轮询降级模式下立即拉取一次） */
  const refresh = useCallback(() => {
    if (pollFnRef.current) {
      void pollFnRef.current()
    }
  }, [])

  useEffect(() => {
    if (!enabled) return

    /** 启动轮询降级（清理 SSE + 设置定时器） */
    const startPolling = (): void => {
      if (eventSourceRef.current) {
        eventSourceRef.current.close()
        eventSourceRef.current = null
      }
      pollFnRef.current = fetchOnce
      void fetchOnce()
      pollTimerRef.current = setInterval(() => {
        void fetchOnce()
      }, fallbackPollInterval)
    }

    /** 清理轮询定时器 */
    const clearPolling = (): void => {
      if (pollTimerRef.current) {
        clearInterval(pollTimerRef.current)
        pollTimerRef.current = null
      }
    }

    // 浏览器不支持 EventSource — 直接使用轮询降级
    if (typeof window === "undefined" || !("EventSource" in window)) {
      startPolling()
      // 延迟状态更新，避免 effect 内同步 setState
      queueMicrotask(() => {
        setIsUsingFallback(true)
        setIsConnected(false)
      })
      return clearPolling
    }

    // 创建 SSE 连接
    let eventSource: EventSource
    try {
      eventSource = new EventSource("/api/notifications/stream")
      eventSourceRef.current = eventSource
    } catch {
      // EventSource 构造失败 — 降级为轮询
      startPolling()
      queueMicrotask(() => {
        setIsUsingFallback(true)
        setIsConnected(false)
      })
      return clearPolling
    }

    eventSource.onopen = () => {
      setIsConnected(true)
      setIsUsingFallback(false)
    }

    eventSource.onmessage = (event) => {
      try {
        if (event.data === "[DONE]") {
          eventSource.close()
          setIsConnected(false)
          // SSE 关闭后降级为轮询
          startPolling()
          setIsUsingFallback(true)
          return
        }
        const data = JSON.parse(event.data) as NotificationStreamData
        if (data.type === "update") {
          if (typeof data.unreadCount === "number") setUnreadCount(data.unreadCount)
          if (data.notifications) setNotifications(data.notifications)
        } else if (data.type === "error") {
          eventSource.close()
          setIsConnected(false)
          startPolling()
          setIsUsingFallback(true)
        }
      } catch {
        // 忽略解析错误
      }
    }

    eventSource.onerror = () => {
      eventSource.close()
      setIsConnected(false)
      startPolling()
      setIsUsingFallback(true)
    }

    return () => {
      eventSource.close()
      clearPolling()
    }
  }, [enabled, fallbackPollInterval, fetchOnce])

  return {
    unreadCount,
    notifications,
    isConnected,
    isUsingFallback,
    refresh,
  }
}
