package com.ssyf.task.service;

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

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * ASR语音解析拉取服务
 * 定时拉取主播ASR解析的消息，并进行智能频率调整
 * 
 * @author system
 * @since 1.0
 */
@Slf4j
@Service
public class AsrSpeechPullService {

    @Autowired
    private AsrSpeechManagerService asrSpeechManagerService;

    @Autowired
    private BusinessService businessService;

    @Autowired
    private WsMessageStorageService wsMessageStorageService;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    // Redis Key前缀：ASR拉取频率配置
    private static final String REDIS_PREFIX_ASR_PULL_FREQUENCY = "asr:speech:pull:freq:";
    // Redis Key前缀：ASR拉取延迟记录
    private static final String REDIS_PREFIX_ASR_PULL_DELAY = "asr:speech:pull:delay:";
    // Redis Key前缀：ASR拉取历史记录
    private static final String REDIS_PREFIX_ASR_PULL_HISTORY = "asr:speech:pull:history:";

    // 默认拉取间隔（秒）
    private static final int DEFAULT_PULL_INTERVAL = 10;
    // 最小拉取间隔（秒）
    private static final int MIN_PULL_INTERVAL = 5;
    // 最大拉取间隔（秒）
    private static final int MAX_PULL_INTERVAL = 60;
    // 延迟阈值（秒）- 超过此值认为消息延迟严重
    private static final int DELAY_THRESHOLD = 30;

    /**
     * 主播ASR拉取定时任务
     * 默认10秒执行一次，根据消息延迟情况智能调整频率
     */
    @Scheduled(fixedDelay = DEFAULT_PULL_INTERVAL * 1000)
    public void pullAsrSpeechMessages() {
        try {
            // 1. 获取已开启ASR解析的直播间列表
            List<Integer> activeRooms = asrSpeechManagerService.getActiveAsrRooms();
            if (CollUtil.isEmpty(activeRooms)) {
                log.debug("当前没有已开启ASR解析的直播间");
                return;
            }

            log.debug("开始拉取ASR解析消息，直播间数量: {}", activeRooms.size());

            // 2. 遍历每个直播间，拉取ASR解析消息
            for (Integer roomId : activeRooms) {
                try {
                    pullAsrSpeechForRoom(roomId);
                } catch (Exception e) {
                    log.error("拉取直播间ASR解析消息异常，主播ID: {}", roomId, e);
                }
            }

        } catch (Exception e) {
            log.error("ASR拉取定时任务异常", e);
        }
    }

    /**
     * 拉取指定直播间的ASR解析消息
     */
    private void pullAsrSpeechForRoom(Integer roomId) {
        // 1. 获取当前拉取频率
        int pullInterval = getPullInterval(roomId);
        
        // 2. 检查是否需要拉取（基于频率控制）
        if (!shouldPullNow(roomId, pullInterval)) {
            return;
        }

        // 3. 记录拉取开始时间
        long pullStartTime = System.currentTimeMillis();

        // 4. 调用业务服务拉取ASR解析消息
        ApiResponse<List<AsrSpeechText>> response = businessService.getAsrSpeechText(roomId);
        if(!response.isSuccess()){
            return;
        }
        List<AsrSpeechText> speechTexts = response.getData();
        
        // 5. 记录拉取结束时间
        long pullEndTime = System.currentTimeMillis();
        long pullDuration = pullEndTime - pullStartTime;

        // 6. 处理拉取到的消息
        if (CollUtil.isNotEmpty(speechTexts)) {
            processSpeechTexts(roomId, speechTexts, pullStartTime);
        }

        // 7. 分析消息延迟情况，智能调整拉取频率
        analyzeAndAdjustFrequency(roomId, speechTexts, pullDuration);

        // 8. 记录拉取历史
        recordPullHistory(roomId, pullStartTime, speechTexts != null ? speechTexts.size() : 0);

        log.debug("ASR解析消息拉取完成，主播ID: {}, 消息数量: {}, 耗时: {}ms", 
                roomId, speechTexts != null ? speechTexts.size() : 0, pullDuration);
    }

    /**
     * 处理ASR解析消息
     */
    private void processSpeechTexts(Integer roomId, List<AsrSpeechText> speechTexts, long pullTime) {
        // 1. 获取直播间信息
        LiveRoom roomInfo = asrSpeechManagerService.getRoomInfo(roomId);
        String anchorName = roomInfo != null && StrUtil.isNotBlank(roomInfo.getNick_name()) 
                ? roomInfo.getNick_name() : "未知主播";

        // 2. 处理每条消息
        for (AsrSpeechText speechText : speechTexts) {
            try {
                // 计算消息延迟
                long messageDelay = pullTime - (speechText.getTime() * 1000L);
                
                // 存储消息到WS消息存储服务
                wsMessageStorageService.bufferMessage(
                    roomId, 
                    anchorName, 
                    "asr_speech", 
                    speechText.getContent(), 
                    JSONUtil.toJsonStr(speechText),
                    "anchor",  // 来源角色：主播
                    StrUtil.isNotBlank(roomInfo.getUser_number()) ? roomInfo.getUser_number() : roomInfo.getUser_id() + ""
                );

                log.debug("存储ASR解析消息，主播ID: {}, 内容: {}, 延迟: {}ms", 
                        roomId, speechText.getContent(), messageDelay);

            } catch (Exception e) {
                log.error("处理ASR解析消息异常，主播ID: {}, 消息: {}", roomId, speechText, e);
            }
        }
    }

    /**
     * 分析消息延迟情况并智能调整拉取频率
     */
    private void analyzeAndAdjustFrequency(Integer roomId, List<AsrSpeechText> speechTexts, long pullDuration) {
        try {
            // 1. 计算平均消息延迟
            double avgDelay = calculateAverageDelay(roomId, speechTexts, pullDuration);
            
            // 2. 根据延迟情况调整频率
            int newInterval = adjustPullInterval(roomId, avgDelay);
            
            // 3. 更新拉取频率
            updatePullInterval(roomId, newInterval);
            
            log.debug("ASR拉取频率调整，主播ID: {}, 平均延迟: {}ms, 新间隔: {}秒", 
                    roomId, avgDelay, newInterval);

        } catch (Exception e) {
            log.error("分析ASR拉取频率异常，主播ID: {}", roomId, e);
        }
    }

    /**
     * 计算平均消息延迟
     */
    private double calculateAverageDelay(Integer roomId, List<AsrSpeechText> speechTexts, long pullDuration) {
        if (CollUtil.isEmpty(speechTexts)) {
            // 如果没有消息，使用拉取耗时作为延迟参考
            return pullDuration;
        }

        long totalDelay = 0;
        int validCount = 0;
        long currentTime = System.currentTimeMillis();

        for (AsrSpeechText speechText : speechTexts) {
            if (speechText.getTime() != null) {
                long messageTime = speechText.getTime() * 1000L;
                long delay = currentTime - messageTime;
                totalDelay += delay;
                validCount++;
            }
        }

        return validCount > 0 ? (double) totalDelay / validCount : pullDuration;
    }

    /**
     * 根据延迟情况调整拉取间隔
     */
    private int adjustPullInterval(Integer roomId, double avgDelay) {
        // 获取当前间隔
        int currentInterval = getPullInterval(roomId);
        
        // 延迟严重（超过阈值），增加拉取间隔
        if (avgDelay > DELAY_THRESHOLD * 1000) {
            return Math.min(currentInterval + 5, MAX_PULL_INTERVAL);
        }
        // 延迟较小，减少拉取间隔（更频繁拉取）
        else if (avgDelay < 5000) { // 5秒内
            return Math.max(currentInterval - 2, MIN_PULL_INTERVAL);
        }
        // 延迟适中，保持当前间隔或微调
        else {
            return currentInterval;
        }
    }

    /**
     * 获取当前拉取间隔
     */
    private int getPullInterval(Integer roomId) {
        try {
            String key = REDIS_PREFIX_ASR_PULL_FREQUENCY + roomId;
            Object intervalObj = redisTemplate.opsForValue().get(key);
            if (intervalObj instanceof Integer) {
                return (Integer) intervalObj;
            } else if (intervalObj instanceof String) {
                return Integer.parseInt((String) intervalObj);
            }
        } catch (Exception e) {
            log.debug("获取ASR拉取间隔异常，使用默认值，主播ID: {}", roomId);
        }
        
        return DEFAULT_PULL_INTERVAL;
    }

    /**
     * 更新拉取间隔
     */
    private void updatePullInterval(Integer roomId, int interval) {
        try {
            String key = REDIS_PREFIX_ASR_PULL_FREQUENCY + roomId;
            redisTemplate.opsForValue().set(key, interval, 24, TimeUnit.HOURS);
        } catch (Exception e) {
            log.error("更新ASR拉取间隔异常，主播ID: {}", roomId, e);
        }
    }

    /**
     * 检查当前是否需要拉取
     */
    private boolean shouldPullNow(Integer roomId, int pullInterval) {
        try {
            String key = REDIS_PREFIX_ASR_PULL_HISTORY + roomId;
            Object lastPullTimeObj = redisTemplate.opsForValue().get(key);
            
            if (lastPullTimeObj == null) {
                return true; // 从未拉取过，需要拉取
            }
            
            long lastPullTime;
            if (lastPullTimeObj instanceof Long) {
                lastPullTime = (Long) lastPullTimeObj;
            } else if (lastPullTimeObj instanceof String) {
                lastPullTime = Long.parseLong((String) lastPullTimeObj);
            } else {
                return true; // 格式异常，需要拉取
            }
            
            long currentTime = System.currentTimeMillis();
            long timeSinceLastPull = currentTime - lastPullTime;
            
            return timeSinceLastPull >= pullInterval * 1000L;
            
        } catch (Exception e) {
            log.debug("检查ASR拉取时间异常，继续拉取，主播ID: {}", roomId);
            return true;
        }
    }

    /**
     * 记录拉取历史
     */
    private void recordPullHistory(Integer roomId, long pullTime, int messageCount) {
        try {
            String key = REDIS_PREFIX_ASR_PULL_HISTORY + roomId;
            redisTemplate.opsForValue().set(key, pullTime, 24, TimeUnit.HOURS);
            
            // 记录延迟信息（用于统计分析）
            String delayKey = REDIS_PREFIX_ASR_PULL_DELAY + roomId;
            redisTemplate.opsForList().rightPush(delayKey, System.currentTimeMillis());
            // 保留最近100条延迟记录
            redisTemplate.opsForList().trim(delayKey, -100, -1);
            redisTemplate.expire(delayKey, 1, TimeUnit.HOURS);
            
        } catch (Exception e) {
            log.error("记录ASR拉取历史异常，主播ID: {}", roomId, e);
        }
    }

    /**
     * 获取指定直播间的当前拉取间隔
     */
    public int getCurrentPullInterval(Integer roomId) {
        return getPullInterval(roomId);
    }

    /**
     * 手动触发ASR消息拉取（用于测试或特殊情况）
     */
    public void triggerPullAsrSpeech(Integer roomId) {
        if (roomId == null) {
            log.warn("手动触发ASR拉取失败：主播ID为空");
            return;
        }

        try {
            pullAsrSpeechForRoom(roomId);
            log.info("手动触发ASR拉取成功，主播ID: {}", roomId);
        } catch (Exception e) {
            log.error("手动触发ASR拉取异常，主播ID: {}", roomId, e);
        }
    }
}