import { bumpOptimisticUnread } from '@/lib/notifications/unreadBadge'
import { isNotificationUnread } from '@/lib/notifications/notificationUnread'
import type { UserNotificationWsPayload } from '@/lib/notifications/userNotificationTypes'
import { decryptWsPayload, encryptWsPayload } from '@/utils/wsCrypto'

export const USER_NOTIFICATIONS_UPDATED_EVENT = 'gp-live:user-notifications-updated'
export const USER_NOTIFICATIONS_LIST_EVENT = 'gp-live:user-notifications-list'
export const SESSION_CHANGED_EVENT = 'gp-live:session-changed'

export type UserNotificationListItem = {
    id: string
    type: string
    title: string
    content: string
    url: string | null
    isRead: boolean
    createdAt: number
    date: string
}

export type UserNotificationsUpdatedDetail = {
    payload?: UserNotificationWsPayload
}

export type UserNotificationsListDetail = {
    notifications: UserNotificationListItem[]
}

export function dispatchSessionChanged() {
    if (typeof window === 'undefined') return
    window.dispatchEvent(new CustomEvent(SESSION_CHANGED_EVENT))
}

export function dispatchUserNotificationsUpdated(payload?: UserNotificationWsPayload) {
    if (typeof window === 'undefined') return
    if (payload && isNotificationUnread(payload)) {
        bumpOptimisticUnread()
    }
    const detail: UserNotificationsUpdatedDetail = payload ? { payload } : {}
    window.dispatchEvent(
        new CustomEvent<UserNotificationsUpdatedDetail>(USER_NOTIFICATIONS_UPDATED_EVENT, {
            detail,
        })
    )
}

export function dispatchUserNotificationsList(notifications: UserNotificationListItem[]) {
    if (typeof window === 'undefined') return
    const detail: UserNotificationsListDetail = { notifications }
    window.dispatchEvent(
        new CustomEvent<UserNotificationsListDetail>(USER_NOTIFICATIONS_LIST_EVENT, { detail })
    )
}

export function buildNoticeWsUrl(): string {
    if (typeof window === 'undefined') return ''

    const wsPort = process.env.NEXT_PUBLIC_WS_PORT || '3001'
    const hostname = window.location.hostname
    const isLocalHost = hostname === 'localhost' || hostname === '127.0.0.1'
    const isDevPort =
        process.env.NODE_ENV === 'development' && window.location.port === '3000'

    // 本機 Next 開發：一律連同機 WS 埠，不依賴 NEXT_PUBLIC_WS_URL（可能指向正式站）
    if (isLocalHost || isDevPort) {
        return `ws://${hostname}:${wsPort}/notice`
    }

    const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'
    const fromEnv = process.env.NEXT_PUBLIC_WS_URL?.trim()
    if (fromEnv) {
        return fromEnv.replace(/\/(ws|chat|streams)\/?$/, '/notice')
    }
    return `${protocol}//${window.location.host}/notice`
}

export function sendNoticeWs(ws: WebSocket, payload: Record<string, unknown>) {
    ws.send(encryptWsPayload(payload))
}

export function sendNoticeSubscribe(ws: WebSocket, userId: string) {
    sendNoticeWs(ws, { type: 'subscribe', userId: String(userId).trim() })
}

export type ParsedNoticeWsMessage = {
    type: string
    requestId?: string
    data?: UserNotificationWsPayload & {
        notifications?: UserNotificationListItem[]
        ok?: boolean
        notificationId?: string
        userId?: string
        message?: string
    }
    error?: string
    message?: string
}

export function parseNoticeWsMessage(data: string): ParsedNoticeWsMessage | null {
    const raw = decryptWsPayload(data)
    if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return null
    const row = raw as ParsedNoticeWsMessage
    return typeof row.type === 'string' ? row : null
}

