package com.ssyf.task.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.ssyf.task.websocket.LiveRoomWsManager;
import com.ssyf.task.websocket.WsMessageStorageService;
import com.ssyf.third.bmiss.model.ApiResponse;
import com.ssyf.third.bmiss.model.OtherUserCenter;
import com.ssyf.third.bmiss.services.BusinessService;
import com.ssyf.third.bmiss.services.LiveService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * 直播间状态监听服务
 * 独立监控直播间状态变化，特别是直播间关闭事件
 * 当检测到直播间关闭时，通知相关服务进行清理
 * 
 * @author system
 * @since 1.0
 */
@Slf4j
@Service
public class LiveRoomStatusMonitorService {

    @Autowired @Lazy
    private BusinessService businessService;
    
    @Autowired @Lazy
    private LiveService liveService;
    
    @Autowired @Lazy
    private LiveRoomMonitorService liveRoomMonitorService;
    
    @Autowired @Lazy
    private AsrSpeechManagerService asrSpeechManagerService;
    
    @Autowired @Lazy
    private LiveRoomWsManager liveRoomWsManager;
    
    @Autowired @Lazy
    private WsMessageStorageService wsMessageStorageService;
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    // 直播间状态缓存相关常量
    private static final String LIVE_ROOM_STATUS_CACHE_PREFIX = "live:room:status:";
    private static final long LIVE_ROOM_STATUS_CACHE_TIME = 5; // 5分钟
    
    // 正在监控的直播间集合
    private final Set<Integer> monitoringRooms = ConcurrentHashMap.newKeySet();
    
    // 直播间关闭事件监听器
    private final List<LiveRoomCloseListener> closeListeners = new ArrayList<>();

    /**
     * 添加直播间到监控列表
     * 
     * @param roomId 直播间ID
     */
    public void addRoomToMonitor(Integer roomId) {
        if (roomId == null) {
            return;
        }
        
        monitoringRooms.add(roomId);
        log.debug("添加直播间到监控列表: {}", roomId);
    }

    /**
     * 从监控列表移除直播间
     * 
     * @param roomId 直播间ID
     */
    public void removeRoomFromMonitor(Integer roomId) {
        if (roomId == null) {
            return;
        }
        
        monitoringRooms.remove(roomId);
        log.debug("从监控列表移除直播间: {}", roomId);
    }

    /**
     * 定时检查直播间状态
     * 每30秒执行一次
     */
    @Scheduled(fixedDelay = 30000)
    public void checkRoomStatus() {
        if (monitoringRooms.isEmpty()) {
            return;
        }

        log.debug("开始检查直播间状态，监控房间数: {}", monitoringRooms.size());
        
        // 批量检查直播间状态
        List<Integer> roomsToCheck = new ArrayList<>(monitoringRooms);
        
        for (Integer roomId : roomsToCheck) {
            try {
                checkSingleRoomStatus(roomId);
            } catch (Exception e) {
                log.error("检查直播间状态异常，roomId: {}", roomId, e);
            }
        }
    }

    /**
     * 检查单个直播间状态
     * 
     * @param roomId 直播间ID
     */
    private void checkSingleRoomStatus(Integer roomId) {
        if (roomId == null) {
            return;
        }

        // 获取直播间状态
        ApiResponse<OtherUserCenter> stateResp = getLiveRoomStatus(roomId);
        
        // 判断直播间是否关闭
        if (isRoomClosed(stateResp)) {
            log.info("检测到直播间已关闭，roomId: {}", roomId);
            
            // 触发直播间关闭事件
            handleRoomClosed(roomId);
            
            // 从监控列表移除
            removeRoomFromMonitor(roomId);
        } else {
            log.debug("直播间状态正常，roomId: {}", roomId);
        }
    }

    /**
     * 获取直播间状态（带缓存）
     * 
     * @param roomId 直播间ID
     * @return 直播间状态响应
     */
    private ApiResponse<OtherUserCenter> getLiveRoomStatus(Integer roomId) {
        // 缓存未命中，调用业务接口
        ApiResponse<OtherUserCenter> response = businessService.getOtherUserCenter(roomId);

        return response;
    }

    /**
     * 判断直播间是否关闭
     * 
     * @param resp 直播间状态响应
     * @return true表示已关闭，false表示正常
     */
    private boolean isRoomClosed(ApiResponse<OtherUserCenter> resp) {
        if (!resp.isSuccess()) {
            return true;
        }
        
        Integer isShowing = resp.getData().getIs_showing();
        return isShowing != null && isShowing == 0;
    }

    /**
     * 处理直播间关闭事件
     * 
     * @param roomId 直播间ID
     */
    private void handleRoomClosed(Integer roomId) {
        if (roomId == null) {
            return;
        }

        log.info("开始处理直播间关闭事件，roomId: {}", roomId);
        
        try {
            // 1. 通知LiveRoomMonitorService退出该直播间的机器人
            notifyLiveRoomMonitorService(roomId);
            
            // 2. 通知ASR管理服务清理缓存并退出解析
            notifyAsrSpeechManagerService(roomId);
            
            // 3. 更新直播间缓存
            notifyLiveService(roomId);
            
            // 4. 关闭WebSocket连接
            notifyWebSocketService(roomId);
            
            // 5. 清理消息缓存
            notifyMessageStorageService(roomId);
            
            log.info("直播间关闭事件处理完成，roomId: {}", roomId);
            
        } catch (Exception e) {
            log.error("处理直播间关闭事件异常，roomId: {}", roomId, e);
        }
    }

    /**
     * 通知LiveRoomMonitorService退出该直播间的机器人
     */
    private void notifyLiveRoomMonitorService(Integer roomId) {
        try {
            liveRoomMonitorService.quitAllRobotsInRoom(roomId);
            log.info("LiveRoomMonitorService退出直播间机器人完成，roomId: {}", roomId);
        } catch (Exception e) {
            log.error("通知LiveRoomMonitorService异常，roomId: {}", roomId, e);
        }
    }

    /**
     * 通知ASR管理服务清理缓存并退出解析
     */
    private void notifyAsrSpeechManagerService(Integer roomId) {
        try {
            // 强制结束ASR解析
            boolean success = asrSpeechManagerService.forceEndAsr(roomId);
            if (success) {
                log.info("ASR解析强制结束成功，roomId: {}", roomId);
            } else {
                log.warn("ASR解析强制结束失败，roomId: {}", roomId);
            }
        } catch (Exception e) {
            log.error("通知ASR管理服务异常，roomId: {}", roomId, e);
        }
    }

    /**
     * 更新直播间缓存
     */
    private void notifyLiveService(Integer roomId) {
        try {
            // 清除指定直播间的缓存
            liveService.clearLiveRoomCache(roomId.longValue());
            log.info("直播间缓存已清除，roomId: {}", roomId);
        } catch (Exception e) {
            log.error("更新直播间缓存异常，roomId: {}", roomId, e);
        }
    }

    /**
     * 关闭WebSocket连接
     */
    private void notifyWebSocketService(Integer roomId) {
        try {
            // 关闭指定直播间的WebSocket连接
            liveRoomWsManager.closeRoomConnection(roomId);
            log.info("WebSocket连接已关闭，roomId: {}", roomId);
        } catch (Exception e) {
            log.error("关闭WebSocket连接异常，roomId: {}", roomId, e);
        }
    }

    /**
     * 清理消息缓存
     */
    private void notifyMessageStorageService(Integer roomId) {
        try {
            wsMessageStorageService.clearRoomMessageCache(roomId);
            log.info("WsMessageStorageService清理消息缓存完成，roomId: {}", roomId);
        } catch (Exception e) {
            log.error("清理消息缓存异常，roomId: {}", roomId, e);
        }
    }

    /**
     * 获取当前监控的直播间列表
     * 
     * @return 直播间ID列表
     */
    public List<Integer> getMonitoringRooms() {
        return new ArrayList<>(monitoringRooms);
    }

    /**
     * 清空监控列表（用于系统重置）
     */
    public void clearMonitoringRooms() {
        monitoringRooms.clear();
        log.info("直播间监控列表已清空");
    }

    /**
     * 直播间关闭事件监听器接口
     */
    public interface LiveRoomCloseListener {
        /**
         * 直播间关闭事件回调
         * 
         * @param roomId 直播间ID
         */
        void onRoomClosed(Integer roomId);
    }

    /**
     * 添加直播间关闭事件监听器
     * 
     * @param listener 监听器
     */
    public void addCloseListener(LiveRoomCloseListener listener) {
        if (listener != null) {
            closeListeners.add(listener);
        }
    }

    /**
     * 移除直播间关闭事件监听器
     * 
     * @param listener 监听器
     */
    public void removeCloseListener(LiveRoomCloseListener listener) {
        if (listener != null) {
            closeListeners.remove(listener);
        }
    }
}