package com.zksy.web.websocket;

import com.alibaba.fastjson.JSONObject;
import com.zksy.base.domain.EquipmentStatus;
import com.zksy.base.service.EquipmentStatusService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.Set;

/**
 * Redis 设备状态变更监听器
 * <p>
 * 监听 Redis 频道 {@code device:status:change}，当 zk-api-service 更新设备报警状态后，
 * 接收消息 → 查询最新设备状态 → 推送到所有订阅了该设备的 WebSocket 会话。
 *
 * @author zksy
 */
@Slf4j
@Component
public class DeviceStatusRedisListener implements MessageListener {

    @Autowired
    private SubscriptionManager subscriptionManager;

    @Autowired
    private EquipmentStatusService equipmentStatusService;

    /**
     * Redis 频道名称
     */
    public static final String CHANNEL = "device:status:change";

    @Override
    public void onMessage(Message message, byte[] pattern) {
        String body = new String(message.getBody());
        log.debug("收到 Redis 设备状态变更消息: channel={}, body={}", CHANNEL, body);

        try {
            JSONObject msgObj = JSONObject.parseObject(body);
            String deviceCode = msgObj.getString("deviceCode");

            if (deviceCode == null || deviceCode.isEmpty()) {
                log.warn("Redis 消息缺少 deviceCode 字段: {}", body);
                return;
            }

            // 查找订阅了该设备的所有 WebSocket 会话
            Set<String> sessionIds = subscriptionManager.getSubscribedSessions(deviceCode);
            if (sessionIds.isEmpty()) {
                log.debug("无会话订阅设备: deviceCode={}", deviceCode);
                return;
            }

            // 查询最新设备状态
            EquipmentStatus status = equipmentStatusService.getByDeviceCode(deviceCode);
            if (status == null) {
                log.warn("未找到设备状态: deviceCode={}", deviceCode);
                return;
            }

            // 构建推送消息
            JSONObject pushMsg = new JSONObject();
            pushMsg.put("type", "deviceStatusPush");
            pushMsg.put("data", status);

            String pushPayload = pushMsg.toJSONString();
            TextMessage textMessage = new TextMessage(pushPayload);

            // 推送到所有订阅了该设备的会话
            int successCount = 0;
            int failCount = 0;
            for (String sessionId : sessionIds) {
                try {
                    WebSocketSession session = DeviceStatusWebSocketHandler.getSession(sessionId);
                    if (session != null && session.isOpen()) {
                        synchronized (session) {
                            session.sendMessage(textMessage);
                        }
                        successCount++;
                    } else {
                        // 会话已失效，清理订阅
                        subscriptionManager.removeSession(sessionId);
                        failCount++;
                    }
                } catch (IOException e) {
                    log.error("推送设备状态失败: sessionId={}, deviceCode={}", sessionId, deviceCode, e);
                    subscriptionManager.removeSession(sessionId);
                    failCount++;
                }
            }

            log.info("设备状态推送完成: deviceCode={}, 成功={}, 失败={}, 订阅会话数={}",
                    deviceCode, successCount, failCount, sessionIds.size());

        } catch (Exception e) {
            log.error("处理 Redis 设备状态变更消息异常: body={}", body, e);
        }
    }
}