import { decryptWsPayload, encryptWsPayload } from '@/utils/wsCrypto'

/** 聊天 WS `data` 欄位（各 type 共用，欄位依事件為選用） */
export type ChatWsPayloadData = {
    userId?: string | null
    userType?: 'streamer' | 'manager' | 'superAdmin'
    id?: string
    author?: string
    text?: string
    isSystem?: boolean
    isModeratorOnly?: boolean
    createdAtMs?: number
    mentions?: unknown[]
    emojis?: unknown[]
    bannedUserId?: string
    unbannedUserId?: string
    adminUserId?: string
    adminUserType?: string
    moddedUserId?: string
    unmoddedUserId?: string
    systemMessageType?: string
    systemMessageData?: unknown
    authorPublicPathKey?: string
    isMod?: boolean
    isSuperAdmin?: boolean
    isBanned?: boolean
    isPermanent?: boolean
    expiresAt?: number | null
    remainingMs?: number | null
    reason?: string | null
    messageId?: string
    deletedBy?: {
        userId?: string
        author?: string
        userType?: string
    }
    message?: ChatWsPayloadData
    participants?: Array<{
        userId?: string | null
        author?: string
        id?: string
        publicPathKey?: string | null
        displayId?: string | null
    }>
    avatar?: string | null
    vipLevel?: string
    avatarFrame?: { id?: string; image?: string; type?: string } | null
    viewers?: number
    chatDisabled?: boolean
    gift?: unknown
    /** `gift_sent` 扣款後餘額 */
    coinBalance?: number
}

export type ChatWsBanInfo = {
    isPermanent?: boolean
    expiresAt?: number | null
    remainingMs?: number | null
    reason?: string | null
}

export type ParsedChatWsMessage = {
    type: string
    data?: ChatWsPayloadData
    messageKey?: string
    banInfo?: ChatWsBanInfo | null
    /** `gift_error` 等事件回傳的目前餘額 */
    coinBalance?: number
}

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

/** 客戶端 WS handler 用：欄位依 type 變化，以寬鬆型別承接既有邏輯 */
export type LooseChatWsMessage = {
    type: string
    data: Record<string, any>
    messageKey?: string
    banInfo?: ChatWsBanInfo | null
    [key: string]: any
}

function toLoosePayloadData(value: unknown): Record<string, any> | undefined {
    if (!value || typeof value !== 'object' || Array.isArray(value)) return undefined
    return value as Record<string, any>
}

export function parseChatWsMessageLoose(data: string): LooseChatWsMessage | null {
    const raw = decryptWsPayload(data)
    if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return null
    const row = raw as Record<string, unknown>
    if (typeof row.type !== 'string') return null
    return {
        ...(row as Record<string, any>),
        type: row.type,
        data: toLoosePayloadData(row.data) ?? {},
        messageKey: typeof row.messageKey === 'string' ? row.messageKey : undefined,
        banInfo: row.banInfo as ChatWsBanInfo | null | undefined,
    }
}

export type ChatJoinPayload = {
    type: 'join'
    roomId: string
    userId?: string
    author: string
}

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

    const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'
    const isLocal = window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1'
    const wsPort = process.env.NEXT_PUBLIC_WS_PORT || '3001'
    const defaultUrl = isLocal
        ? `ws://${window.location.hostname}:${wsPort}/chat`
        : `${protocol}//${window.location.host}/chat`
    if (isLocal) return defaultUrl
    const fromEnv = process.env.NEXT_PUBLIC_WS_URL?.trim()
    if (fromEnv) return fromEnv.replace(/\/(ws|chat)\/?$/, '/chat')
    return defaultUrl
}

export function buildChatJoinPayload(params: {
    roomId: string
    userId?: string | null
    author: string
}): ChatJoinPayload {
    const userId = String(params.userId ?? '').trim()
    return {
        type: 'join',
        roomId: params.roomId,
        ...(userId ? { userId } : {}),
        author: String(params.author ?? '').trim() || '遊客',
    }
}

export function sendChatJoin(
    ws: WebSocket,
    params: { roomId: string; userId?: string | null; author: string }
) {
    ws.send(encryptWsPayload(buildChatJoinPayload(params)))
}
