package com.narutohuo.xindazhou.socketio.repository

import com.narutohuo.xindazhou.core.log.ILog
import com.narutohuo.xindazhou.socketio.api.SocketIOService
import com.narutohuo.xindazhou.socketio.factory.SocketIOServiceFactory
import com.narutohuo.xindazhou.socketio.model.SocketIOEvent
import com.narutohuo.xindazhou.socketio.model.SocketIOResponse
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch

/**
 * SocketIO 数据仓库
 * 
 * 负责统一管理 SocketIO 连接和数据获取
 * 完全封装在 capability-socketio 模块内部，app 模块通过 Factory 获取实例
 */
class SocketIORepository(
    private val socketService: SocketIOService = SocketIOServiceFactory.getInstance()
) {
    
    companion object {
        private const val TAG = "SocketIORepository"
    }
    
    // 使用 extraBufferCapacity 确保事件不丢失
    private val _connectionState = MutableSharedFlow<Boolean>(extraBufferCapacity = 1)
    val connectionState: SharedFlow<Boolean> = _connectionState.asSharedFlow()
    
    private val _logMessage = MutableSharedFlow<String>(extraBufferCapacity = 64)
    val logMessage: SharedFlow<String> = _logMessage.asSharedFlow()
    
    private val _vehicleControlResponse = MutableSharedFlow<SocketIOResponse>(extraBufferCapacity = 1)
    val vehicleControlResponse: SharedFlow<SocketIOResponse> = _vehicleControlResponse.asSharedFlow()
    
    private val _vehicleAlarm = MutableSharedFlow<SocketIOResponse>(extraBufferCapacity = 1)
    val vehicleAlarm: SharedFlow<SocketIOResponse> = _vehicleAlarm.asSharedFlow()
    
    // 用于在回调中发送事件的协程作用域
    private val eventScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
    
    init {
        subscribeEvents()
    }
    
    /**
     * 连接 SocketIO
     * 
     * @param serverUrl SocketIO 服务器地址
     * @param token JWT Token（用于身份验证）
     */
    suspend fun connect(serverUrl: String, token: String): Result<Unit> {
        return try {
            if (token.isNullOrEmpty()) {
                return Result.failure(Exception("未登录，无法获取Token"))
            }
            
            ILog.d(TAG, "connect: 正在连接 $serverUrl")
            socketService.connect(serverUrl, token)
            Result.success(Unit)
        } catch (e: Exception) {
            ILog.e(TAG, "connect: 连接失败", e)
            Result.failure(e)
        }
    }
    
    /**
     * 断开 SocketIO 连接
     */
    suspend fun disconnect(): Result<Unit> {
        return try {
            socketService.disconnect()
            ILog.d(TAG, "disconnect: 已断开连接")
            Result.success(Unit)
        } catch (e: Exception) {
            ILog.e(TAG, "disconnect: 断开连接失败", e)
            Result.failure(e)
        }
    }
    
    /**
     * 检查连接状态
     */
    fun isConnected(): Boolean {
        return socketService.isConnected()
    }
    
    /**
     * 检查连接状态，如果断开则自动重连
     * 
     * 用于 App 进入前台时自动重连的场景
     * 
     * @param serverUrl SocketIO 服务器地址
     * @param token JWT Token（用于身份验证）
     * @return 如果已连接返回 true，如果需要重连则返回 false（重连是异步的）
     */
    suspend fun checkAndReconnect(serverUrl: String, token: String): Boolean {
        return if (socketService.isConnected()) {
            // 已连接，无需重连
            ILog.d(TAG, "checkAndReconnect: 已连接，无需重连")
            true
        } else {
            // 未连接，尝试重连
            ILog.d(TAG, "checkAndReconnect: 未连接，开始重连...")
            connect(serverUrl, token)
                .onSuccess {
                    ILog.d(TAG, "checkAndReconnect: 重连成功")
                }
                .onFailure { e ->
                    ILog.e(TAG, "checkAndReconnect: 重连失败", e)
                }
            false
        }
    }
    
    /**
     * 发送车辆控制指令
     */
    suspend fun sendVehicleControl(command: String, vehicleId: Long): Result<Unit> {
        return try {
            if (!socketService.isConnected()) {
                return Result.failure(Exception("未连接，无法发送消息"))
            }
            
            val data = mapOf(
                "command" to command,
                "vehicleId" to vehicleId,
                "timestamp" to System.currentTimeMillis()
            )
            socketService.emit(SocketIOEvent.VEHICLE_CONTROL, data)
            ILog.d(TAG, "sendVehicleControl: 发送指令 $command")
            Result.success(Unit)
        } catch (e: Exception) {
            ILog.e(TAG, "sendVehicleControl: 发送失败", e)
            Result.failure(e)
        }
    }
    
    /**
     * 订阅 SocketIO 事件
     */
    private fun subscribeEvents() {
        // 订阅连接成功事件
        socketService.on(SocketIOEvent.CONNECT) { response ->
            ILog.d(TAG, "onConnect - 触发连接状态更新")
            // 在协程作用域中使用 emit 确保事件被发送
            eventScope.launch {
                _connectionState.emit(true)
                ILog.d(TAG, "onConnect - 连接状态已更新为 true")
            }
            _logMessage.tryEmit("✅ 连接成功")
        }
        
        // 订阅断开连接事件
        socketService.on(SocketIOEvent.DISCONNECT) { response ->
            ILog.d(TAG, "onDisconnect")
            eventScope.launch {
                _connectionState.emit(false)
            }
            _logMessage.tryEmit("❌ 断开连接")
        }
        
        // 订阅连接错误事件
        socketService.on(SocketIOEvent.CONNECT_ERROR) { response ->
            ILog.e(TAG, "onConnectError: ${response.data}")
            eventScope.launch {
                _connectionState.emit(false)
            }
            _logMessage.tryEmit("❌ 连接错误：${response.data}")
        }
        
        // 订阅车辆控制响应事件
        socketService.on("vehicle_control_response") { response ->
            ILog.d(TAG, "onVehicleControlResponse: ${response.data}")
            _logMessage.tryEmit("📩 收到车辆控制响应：${response.data}")
            _vehicleControlResponse.tryEmit(response)
        }
        
        // 订阅车辆报警事件
        socketService.on(SocketIOEvent.VEHICLE_ALARM) { response ->
            ILog.d(TAG, "onVehicleAlarm: ${response.data}")
            _logMessage.tryEmit("🚨 收到车辆报警推送")
            _logMessage.tryEmit("   事件: ${response.event}")
            _logMessage.tryEmit("   数据: ${response.data}")
            _vehicleAlarm.tryEmit(response)
        }
    }
}

