import { SocketSession } from '@/store/services/socket-session'
import appSettings from '@/core/config/app-settings'
import { bindSocketClient, isLiveRoomPacket } from '@/features/im/socket-bind'
import { setChat } from '@/common/chat-utils.js'

let session = null

function ensureSession(store) {
	if (session) return session
	session = new SocketSession({
		onOpen: () => {
			if (store.state && store.state.im) store.state.im.online = true
			setTimeout(() => {
				if (store.state && store.state.user && store.state.user.isLogin) {
					store.dispatch('im/fetchInbox').catch(() => {})
				}
			}, 300)
			setTimeout(() => {
				uni.$emit('im:connected')
				uni.$emit('websocket:connected')
			}, 500)
		},
		onMessage: (msg) => store.dispatch('im/dispatchPacket', msg),
		onClose: () => { if (store.state && store.state.im) store.state.im.online = false },
		onError: () => { if (store.state && store.state.im) store.state.im.online = false }
	})
	return session
}

export default {
	namespaced: true,
	state: {
		online: false,
		badge: 0,
		inbox: [],
		halted: false
	},
	mutations: {
		setBadge(state, n) {
			state.badge = n
		},
		setInbox(state, list) {
			state.inbox = list || []
		}
	},
	actions: {
		resume({ state }) {
			if (state.halted) {
				state.halted = false
				ensureSession(this).allowReconnect = true
			}
			ensureSession(this).open()
		},
		pause({ state }, permanent = false) {
			const sock = ensureSession(this)
			if (permanent) {
				state.halted = true
				sock.allowReconnect = false
			}
			sock.pause(!permanent)
		},
		async bindClient(_, clientId) {
			await bindSocketClient(clientId)
		},
		dispatchPacket({ dispatch, rootState }, message) {
			let packet
			try {
				packet = JSON.parse(message.data)
			} catch (_) {
				if (appSettings.debug) console.log('[im] non-json packet ignored')
				return
			}

			uni.$emit('im:packet', packet)

			switch (packet?.type) {
				case 'ping':
					ensureSession(this).send({ type: 'pong' })
					return
				case 'init':
					dispatch('bindClient', packet.client_id).catch(() => {})
					return
				case 'chat': {
					// 落本地缓存 + 更新会话列表（对齐 88live chat/onMessage）
					try {
						setChat(packet, 'receive')
					} catch (_) {}
					const form = packet.form || {}
					dispatch(
						'chat/update',
						{
							type: 'chat',
							data: packet,
							shop: {
								id: form.shop_id,
								user_id: form.id,
								name: form.name,
								avatar: form.avatar
							}
						},
						{ root: true }
					).catch(() => {})
					uni.$emit('im:chat', packet)
					uni.$emit('onMessage', packet)
					return
				}
				case 'order':
					dispatch('chat/storage', { type: 'order' }, { root: true }).catch(() => {})
					uni.$emit('im:order', packet)
					return
				case 'notice':
					dispatch('chat/storage', { type: 'notice' }, { root: true }).catch(() => {})
					uni.$emit('im:notice', packet)
					return
				case 'service':
					uni.$emit('onService', packet)
					return
				case 'live':
					uni.$emit('onLiveMessage', packet)
					return
				case 'tip_done':
				case 'end':
				case 'gift':
					uni.$emit('onLiveMessage', packet)
					return
				default:
					break
			}

			if (isLiveRoomPacket(packet)) {
				uni.$emit('onLiveMessage', packet)
			}
		},
		async fetchInbox({ dispatch }) {
			await dispatch('chat/get', null, { root: true })
		}
	}
}
