const WS_APP_URL = 'ws://cloud_test.yuxindazhineng.com'
// (工具类)连接、发送、接收、重连...
class WebSocketManager {
	constructor() {
		this.ws = null
		this.url = `${WS_APP_URL}/cloud_api/phone/app_ws`
		this.options = {
			token: '',
			conversationId: '',
			onMessage: null,
			onError: null,
			onReconnect: null,
			onOpen: null,
			onClose: null
		}
		this.reconnectAttempts = 0
		this.maxReconnectAttempts = 5
		this.reconnectDelay = 3000
		this.reconnectTimer = null
		this.heartbeatTimer = null
		this.isManualClose = false
	}
	/**
	 * 初始化连接
	 * @param {string} url WebSocket URL
	 * @param {Object} options 配置选项
	 */
	connect(options = {}) {
		this.options = {
			...this.options,
			...options
		}
		this.isManualClose = false
		// 关闭现有连接
		if (this.ws) {
			this.close()
		}
		try {
			// #ifdef APP-PLUS || MP-WEIXIN
			this.ws = uni.connectSocket({
				url: this.url,
				success: () => {
					console.log('WebSocket 连接请求已发送');
				},
				fail: (err) => {
					console.error('WebSocket 连接失败:', err)
					this.handleError(err)
				}
			})
			// #endif
			
			// #ifdef H5
			if (!this.ws) {
				this.ws = new WebSocket(this.url)
			}
			// #endif
			
			this.initEventHandlers()
		} catch (err) {
			this.handleError(err)
		}
	}

	/**
	 * 初始化事件处理
	 */
	initEventHandlers() {
		if (!this.ws) return
		
		// #ifdef APP-PLUS || MP-WEIXIN
		// 打开连接
		this.ws.onOpen((event) => {
			console.log('WebSocket 已连接')
			// 修复：先判断重连状态，再重置计数
			if (this.reconnectAttempts > 0) {
				this.options.onReconnect?.()
			}
			this.options.onOpen?.(event)
			this.reconnectAttempts = 0
			// this.startHeartbeat()
		})
		this.ws.onMessage((event) => {

			try {
				const data = JSON.parse(event.data)
				console.log('收到了返回消息：', data);
				// uni.setStorageSync('currentSessionId', data.task_call_id)
				this.handleMessage(data)
			} catch (err) {
				console.error('消息解析失败:', err)
				uni.setStorageSync('currentSessionId', event.data.task_call_id)
			}
		})
		this.ws.onError((err) => {
			console.error('WebSocket 错误:', err)
			this.handleError(err)
		})
		this.ws.onClose((event) => {
			console.log('WebSocket 已关闭:', event.code, event.reason)
			this.options.onClose?.(event)
			this.stopHeartbeat()
			if (!this.isManualClose && this.reconnectAttempts < this.maxReconnectAttempts) {
				this.reconnect()
			}
		})
		// #endif
		
		// #ifdef H5
		// H5 环境使用原生 WebSocket API
		if (typeof WebSocket !== 'undefined') {
			this.ws.onopen = (event) => {
				console.log('WebSocket 已连接 (H5)')
				if (this.reconnectAttempts > 0) {
					this.options.onReconnect?.()
				}
				this.options.onOpen?.(event)
				this.reconnectAttempts = 0
			}
			
			this.ws.onmessage = (event) => {
				try {
					const data = JSON.parse(event.data)
					console.log('收到了返回消息 (H5)：', data);
					this.handleMessage(data)
				} catch (err) {
					console.error('消息解析失败 (H5):', err)
				}
			}
			
			this.ws.onerror = (err) => {
				console.error('WebSocket 错误 (H5):', err)
				this.handleError(err)
			}
			
			this.ws.onclose = (event) => {
				console.log('WebSocket 已关闭 (H5):', event.code, event.reason)
				this.options.onClose?.(event)
				this.stopHeartbeat()
				if (!this.isManualClose && this.reconnectAttempts < this.maxReconnectAttempts) {
					this.reconnect()
				}
			}
		}
		// #endif
	}

	
	/**
	 * 处理服务端推送的消息
	 * @param {Object} msg - 服务端返回的原始消息对象
	 */
	handleMessage(msg) {
		this.options.onMessage?.(msg)
		const type = msg.type
		// const data = msg.data || {}
		// 连接确认：服务端认证成功响应
		if (type === 'auth_ok') {
			// 发送消息携带的上一次返回的验证id
			// const taskCallId = data.task_call_id
			// uni.setStorageSync('taskCallId', taskCallId)
			console.log('认证成功，socket连接成功');
			return
		}
		
		// 断开连接指令：服务端主动要求断开
		if (type === 'auth_fail') {
			if(msg?.reason === "pc offline")
			console.log("pc端不在线，不可聊天");
			// console.log('服务端要求断开连接')
			this.isManualClose = true
			this.close()
			return
		}

	}

	/**
	 * 统一发送消息方法
	 * 兼容 APP / 微信小程序 环境
	 * @param {Object} data - 要发送的消息对象
	 * @returns {Promise} 发送结果
	 */
	send(data) {
		
		return new Promise((resolve, reject) => {
			// 未连接直接拒绝
			if (!this.isConnected()) {
				reject(new Error('WebSocket 未连接'))
				return
			}
			const msg = JSON.stringify(data)
			console.log("发送的消息是：", msg);
			
			// #ifdef APP-PLUS || MP-WEIXIN
			// APP / 小程序环境：uni-app 封装 API
			this.ws.send({
				data: msg,
				success: () => resolve(),
				fail: (err) => {
					console.error('发送消息失败:', err)
					reject(err)
				}
			})
			// #endif
			
			// #ifdef H5
			// H5 环境：原生 WebSocket API
			if (this.ws.readyState === WebSocket.OPEN) {
				this.ws.send(msg)
				resolve()
			} else {
				reject(new Error('WebSocket 未打开'))
			}
			// #endif
		})
	}

	/**
	 * 自动重连机制
	 * 指数退避重连，避免频繁重连
	 */
	reconnect() {
		// 已有重连定时器则不重复触发
		if (this.reconnectTimer) return
		this.reconnectAttempts++
		console.log(`尝试重连 (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`)
		// 延迟执行重连，延迟时间随次数递增
		this.reconnectTimer = setTimeout(() => {
			this.reconnectTimer = null
			// 非手动关闭才重连
			if (!this.isManualClose) {
				this.connect(this.options)
			}
		}, this.reconnectDelay * this.reconnectAttempts)
	}

	/**
	 * 启动心跳定时器
	 * 每30秒发送一次 ping 保持连接
	 */
	startHeartbeat() {
		this.stopHeartbeat()
		this.heartbeatTimer = setInterval(() => {
			if (this.isConnected()) {
				this.send({
					ws_event: 'ping'
				}).catch(() => {
					console.log('心跳发送失败，准备重连')
					// 避免在已经重连过程中重复触发
					if (!this.reconnectTimer && !this.isManualClose) {
						this.reconnect()
					}
				})
			} else if (!this.isManualClose && this.reconnectAttempts < this.maxReconnectAttempts) {
				// 连接已断开但未触发 close 事件时主动重连
				this.reconnect()
			}

		}, 30000)
	}
	/**
	 * 停止心跳定时器
	 */
	stopHeartbeat() {
		if (this.heartbeatTimer) {
			clearInterval(this.heartbeatTimer)
			this.heartbeatTimer = null
		}
	}

	/**
	 * 统一错误处理
	 * @param {Error} error - 错误对象
	 */
	handleError(error) {
		console.error('WebSocket 错误处理:', JSON.stringify(error))
		this.options.onError?.(error)
	}

	/**
	 * 判断 WebSocket 是否处于已连接状态
	 * @returns {boolean}
	 */
	isConnected() {
		if (!this.ws) return false
		// #ifdef APP-PLUS || MP-WEIXIN
		return this.ws.readyState === 1
		// #endif
		// #ifdef H5
		return this.ws.readyState === WebSocket.OPEN
		// #endif
	}

	/**
	 * 方便外部获取连接状态码
	 * @returns {number} 0:连接中,1:已连接,2:关闭中,3:已关闭
	 */
	getReadyState() {
		if (!this.ws) return 3
		// #ifdef APP-PLUS || MP-WEIXIN
		return this.ws.readyState
		// #endif
		// #ifdef H5
		return this.ws.readyState
		// #endif
	}
	/**
	 * 手动关闭 WebSocket 连接
	 * 清理所有定时器、标记手动关闭、停止重连
	 */
	close() {
		console.log('手动关闭 WebSocket 连接')
		this.isManualClose = true
		this.stopHeartbeat()

		// 清理重连定时器
		if (this.reconnectTimer) {
			clearTimeout(this.reconnectTimer)
			this.reconnectTimer = null
		}

		if (this.ws) {
			// 移除所有事件监听，避免内存泄漏
			// #ifdef APP-PLUS || MP-WEIXIN
			if (this.ws.onOpen) this.ws.onOpen(null)
			if (this.ws.onMessage) this.ws.onMessage(null)
			if (this.ws.onError) this.ws.onError(null)
			if (this.ws.onClose) this.ws.onClose(null)
			// #endif
			
			try {
				// #ifdef APP-PLUS || MP-WEIXIN
				this.ws.close({
					success: () => console.log('连接已关闭'),
					fail: (err) => console.error('关闭失败:', err)
				})
				// #endif
				
				// #ifdef H5
				this.ws.close()
				// #endif
			} catch (error) {
				console.error('关闭连接出错:', error)
			}
			this.ws = null
		}

		// 重置重连计数
		this.reconnectAttempts = 0
	}
	/**
	 * 更新配置项
	 * 合并新配置，不覆盖原有配置
	 * @param {Object} options - 新配置
	 */
	updateOptions(options) {
		this.options = {
			...this.options,
			...options
		}
	}

}
// 单例实例化，全局唯一
export const socketManager = new WebSocketManager()
export default socketManager