package com.fs.app.taskService.impl;//package com.fs.app.taskService.impl;
//
//import com.alibaba.fastjson.JSON;
//import com.alibaba.fastjson.JSONArray;
//import com.fs.app.taskService.SopLogsTaskService;
//import com.fs.app.taskService.SopLogsTestService;
//import com.fs.common.utils.StringUtils;
//import com.fs.course.config.CourseConfig;
//import com.fs.course.domain.*;
//import com.fs.course.mapper.FsCourseDomainNameMapper;
//import com.fs.course.mapper.FsCourseFinishTempMapper;
//import com.fs.course.mapper.FsCourseLinkMapper;
//import com.fs.course.mapper.FsCourseWatchLogMapper;
//import com.fs.fastgptApi.util.AudioUtils;
//import com.fs.fastgptApi.vo.AudioVO;
//import com.fs.qw.domain.QwExternalContact;
//import com.fs.qw.mapper.QwExternalContactMapper;
//import com.fs.qw.mapper.QwUserMapper;
//import com.fs.qw.vo.QwSopCourseFinishTempSetting;
//import com.fs.qw.vo.QwSopRuleTimeVO;
//import com.fs.qw.vo.QwSopTempSetting;
//import com.fs.sop.domain.QwSopLogs;
//import com.fs.sop.domain.SopUserLogs;
//import com.fs.sop.domain.SopUserLogsInfo;
//import com.fs.sop.mapper.QwSopLogsMapper;
//import com.fs.sop.mapper.QwSopMapper;
//import com.fs.sop.mapper.SopUserLogsInfoMapper;
//import com.fs.sop.mapper.SopUserLogsMapper;
//import com.fs.sop.service.IQwSopLogsService;
//import com.fs.sop.vo.SopUserLogsVo;
//import com.fs.system.service.ISysConfigService;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.retry.annotation.Backoff;
//import org.springframework.retry.annotation.Retryable;
//import org.springframework.scheduling.annotation.Async;
//import org.springframework.scheduling.annotation.Scheduled;
//import org.springframework.stereotype.Service;
//import org.springframework.transaction.annotation.Transactional;
//
//import javax.annotation.PostConstruct;
//import javax.annotation.PreDestroy;
//import java.time.LocalDate;
//import java.time.LocalDateTime;
//import java.time.LocalTime;
//import java.time.ZoneId;
//import java.time.format.DateTimeFormatter;
//import java.time.temporal.ChronoUnit;
//import java.util.ArrayList;
//import java.util.Date;
//import java.util.List;
//import java.util.Map;
//import java.util.concurrent.*;
//import java.util.stream.Collectors;
//
//import static com.fs.course.utils.LinkUtil.generateRandomStringWithLock;
//
//@Service
//@Slf4j
//public class SopLogsTestServiceImpl implements SopLogsTestService {
//
//
//    private static final String REAL_LINK_PREFIX = "https://h5api.ylrzcloud.com/courseh5/pages/course/learning?course=";
//    private static final String QWSOP_KEY_PREFIX = "qwsop:";
//    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
//    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
//
//    // Cached configurations and domain names
//    private CourseConfig cachedCourseConfig;
//    private final Object configLock = new Object();
//
//    private List<FsCourseDomainName> cachedDomainNames;
//    private final Object domainLock = new Object();
//
//
//    // Batch size for database inserts, configurable via application.properties
//    private final int BATCH_SIZE = 1000;
//
//    @Autowired
//    private SopUserLogsMapper sopUserLogsMapper;
//
//    @Autowired
//    private QwSopMapper sopMapper;
//
//    @Autowired
//    private FsCourseWatchLogMapper fsCourseWatchLogMapper;
//
//    @Autowired
//    private IQwSopLogsService qwSopLogsService;
//
//    @Autowired
//    private QwSopLogsMapper qwSopLogsMapper;
//
//    @Autowired
//    private FsCourseLinkMapper fsCourseLinkMapper;
//    @Autowired
//    private ISysConfigService configService;
//
//    @Autowired
//    private FsCourseDomainNameMapper fsCourseDomainNameMapper;
//
//    @Autowired
//    private SopUserLogsInfoMapper sopUserLogsInfoMapper;
//    @Autowired
//    private QwUserMapper qwUserMapper;
//
//    // Blocking queues with bounded capacity to implement backpressure
//    private final BlockingQueue<QwSopLogs> qwSopLogsQueue = new LinkedBlockingQueue<>(10000);
//    private final BlockingQueue<FsCourseWatchLog> watchLogsQueue = new LinkedBlockingQueue<>(10000);
//    private final BlockingQueue<FsCourseLink> linkQueue = new LinkedBlockingQueue<>(10000);
//
//    // Executors for consumer threads
//    private ExecutorService qwSopLogsExecutor;
//    private ExecutorService watchLogsExecutor;
//    private ExecutorService courseLinkExecutor;
//
//    // Shutdown flags
//    private volatile boolean running = true;
//
//
//    @PostConstruct
//    public void init() {
//        loadCourseConfig();
//        loadDomainNames();
//        startConsumers();
//    }
//
//    private void loadCourseConfig() {
//        try {
//            String json = configService.selectConfigByKey("course.config");
//            CourseConfig config = JSON.parseObject(json, CourseConfig.class);
//            if (config != null) {
//                cachedCourseConfig = config;
//                log.info("Loaded course.config successfully.");
//            } else {
//                log.error("Failed to load course.config from configService.");
//            }
//        } catch (Exception e) {
//            log.error("Exception while loading course.config: {}", e.getMessage(), e);
//        }
//    }
//
//    private void loadDomainNames() {
//        try {
//            cachedDomainNames = fsCourseDomainNameMapper.selectAllDomainNames();
//            log.info("Loaded {} domain names for short links.", cachedDomainNames.size());
//        } catch (Exception e) {
//            log.error("Failed to load domain names: {}", e.getMessage(), e);
//        }
//    }
//
//
//    private void startConsumers() {
//        qwSopLogsExecutor = Executors.newSingleThreadExecutor(r -> {
//            Thread t = new Thread(r, "QwSopLogsConsumer");
//            t.setDaemon(true);
//            return t;
//        });
//        watchLogsExecutor = Executors.newSingleThreadExecutor(r -> {
//            Thread t = new Thread(r, "WatchLogsConsumer");
//            t.setDaemon(true);
//            return t;
//        });
//        courseLinkExecutor = Executors.newSingleThreadExecutor(r -> {
//            Thread t = new Thread(r, "courseLinkConsumer");
//            t.setDaemon(true);
//            return t;
//        });
//
//        qwSopLogsExecutor.submit(this::consumeQwSopLogs);
//        watchLogsExecutor.submit(this::consumeWatchLogs);
//        courseLinkExecutor.submit(this::consumeCourseLink);
//    }
//
//    // Scheduled tasks to refresh configurations and domain names periodically
//    @Scheduled(fixedDelay = 60000) // 每60秒刷新一次
//    public void refreshCourseConfig() {
//        synchronized(configLock) {
//            try {
//                String json = configService.selectConfigByKey("course.config");
//                CourseConfig newConfig = JSON.parseObject(json, CourseConfig.class);
//                if (newConfig != null) {
//                    cachedCourseConfig = newConfig;
//                    log.info("Refreshed course.config.");
//                } else {
//                    log.error("Failed to refresh course.config.");
//                }
//            } catch (Exception e) {
//                log.error("Exception while refreshing course.config: {}", e.getMessage(), e);
//            }
//        }
//    }
//
//    @Scheduled(fixedDelay = 60000) // 每60秒刷新一次
//    public void refreshDomainNames() {
//        synchronized(domainLock) {
//            try {
//                cachedDomainNames = fsCourseDomainNameMapper.selectAllDomainNames();
//                log.info("Refreshed {} domain names for short links.", cachedDomainNames.size());
//            } catch (Exception e) {
//                log.error("Failed to refresh domain names: {}", e.getMessage(), e);
//            }
//        }
//    }
//
//
//    @PreDestroy
//    public void shutdownConsumers() {
//        running = false;
//        qwSopLogsExecutor.shutdown();
//        watchLogsExecutor.shutdown();
//        courseLinkExecutor.shutdown();
//        try {
//            if (!qwSopLogsExecutor.awaitTermination(60, TimeUnit.SECONDS)) {
//                qwSopLogsExecutor.shutdownNow();
//            }
//            if (!watchLogsExecutor.awaitTermination(60, TimeUnit.SECONDS)) {
//                watchLogsExecutor.shutdownNow();
//            }
//            if (!courseLinkExecutor.awaitTermination(60, TimeUnit.SECONDS)) {
//                courseLinkExecutor.shutdownNow();
//            }
//        } catch (InterruptedException e) {
//            qwSopLogsExecutor.shutdownNow();
//            watchLogsExecutor.shutdownNow();
//            courseLinkExecutor.shutdownNow();
//            Thread.currentThread().interrupt();
//        }
//    }
//
//    @Override
//    public void selectSopUserLogsListByTest() throws Exception {
//        long startTimeMillis = System.currentTimeMillis();
//        log.info("====== 开始选择和处理 SOP 用户日志 ======");
//
//        List<SopUserLogsVo> sopUserLogsVos = sopUserLogsMapper.selectSopUserLogsListByTest();
//        if (sopUserLogsVos.isEmpty()) {
//            log.info("没有需要处理的 SOP 用户日志。");
//            return;
//        }
//
//        Map<String, List<SopUserLogsVo>> sopLogsGroupedById = sopUserLogsVos.stream()
//                .collect(Collectors.groupingBy(SopUserLogsVo::getSopId));
//
//        log.info("共分组 {} 个 SOP ID 进行处理。", sopLogsGroupedById.size());
//
//        CountDownLatch sopGroupLatch = new CountDownLatch(sopLogsGroupedById.size());
//
//        for (Map.Entry<String, List<SopUserLogsVo>> entry : sopLogsGroupedById.entrySet()) {
//            String sopId = entry.getKey();
//            List<SopUserLogsVo> userLogsVos = entry.getValue();
//            processSopGroupAsync(sopId, userLogsVos, sopGroupLatch);
//        }
//
//        // 等待所有 SOP 分组处理完成
//        sopGroupLatch.await();
//
//        // 触发批量插入（可选，如果需要立即插入队列中的数据）
//        // batchInsertQwSopLogs();
//        // batchInsertFsCourseWatchLogs();
//
//        long endTimeMillis = System.currentTimeMillis();
//        log.info("====== SOP 用户日志处理完成，耗时 {} 毫秒 ======", (endTimeMillis - startTimeMillis));
//    }
//
//    @Async("sopTaskExecutor")
//    @Retryable(
//            value = { Exception.class },
//            maxAttempts = 3,
//            backoff = @Backoff(delay = 2000)
//    )
//    public void processSopGroupAsync(String sopId, List<SopUserLogsVo> userLogsVos, CountDownLatch latch) {
//        try {
//            processSopGroup(sopId, userLogsVos);
//        } catch (Exception e) {
//            log.error("处理 SOP ID {} 时发生异常: {}", sopId, e.getMessage(), e);
//        } finally {
//            latch.countDown();
//        }
//    }
//
//
//    private void processSopGroup(String sopId, List<SopUserLogsVo> userLogsVos) throws Exception {
//        QwSopRuleTimeVO ruleTimeVO = sopMapper.selectQwSopByClickHouseId(sopId);
//
//        if (ruleTimeVO == null) {
////            sopUserLogsMapper.deleteSopUserLogsBySopId(sopId);
//            log.info("SOP ID {} 模板已删除或不存在，相关日志已清除。", sopId);
//            return;
//        }
//
//        if (ruleTimeVO.getStatus() == 0 || "0".equals(ruleTimeVO.getTempStatus())) {
//            SopUserLogs sopUserLogs = new SopUserLogs();
//            sopUserLogs.setSopId(sopId);
//            sopUserLogs.setStatus(2);
//            sopUserLogsMapper.updateSopUserLogsByStatus(sopUserLogs);
//            log.info("SOP ID {} 的状态为停用，相关日志状态已更新。", sopId);
//            return;
//        }
//
//        if (ruleTimeVO.getTempSetting()==null) {
//            log.error("SOP ID {} 的 TempSetting 为空，跳过处理。", sopId);
//            return;
//        }
//
//        //解析模板
//        String jsonData = ruleTimeVO.getTempSetting();
//        List<QwSopTempSetting> tempSettings = new ArrayList<>();
//        if (jsonData.startsWith("[") && jsonData.endsWith("]")) {
//            // 直接解析 JSON 数组
//            tempSettings = JSONArray.parseArray(jsonData, QwSopTempSetting.class);
//        } else {
//            // 先解包，再解析
//            String fixedJson = JSON.parseObject(jsonData, String.class);
//            tempSettings = JSONArray.parseArray(fixedJson, QwSopTempSetting.class);
//        }
//
////        String jsonData = finishTemp.getSetting();
////
////        List<QwSopTempSetting> tempSettings = JSON.parseArray(ruleTimeVO.getTempSetting(), QwSopTempSetting.class);
//        if (tempSettings.isEmpty()) {
//            log.error("SOP ID {} 的 TempSetting 为空，跳过处理。", sopId);
//            return;
//        }
//
//        CountDownLatch userLogsLatch = new CountDownLatch(userLogsVos.size());
//        for (SopUserLogsVo logVo : userLogsVos) {
//            processUserLogAsync(logVo, ruleTimeVO, tempSettings, userLogsLatch);
//        }
//
//        // 等待所有用户日志处理完成
//        try {
//            userLogsLatch.await();
//        } catch (InterruptedException e) {
//            Thread.currentThread().interrupt();
//            log.error("等待用户日志处理完成时被中断: {}", e.getMessage(), e);
//        }
//        log.info("SOP ID {} 的所有用户日志已处理完毕。", sopId);
//    }
//
//    @Async("sopTaskExecutor")
//    @Retryable(
//            value = { Exception.class },
//            maxAttempts = 3,
//            backoff = @Backoff(delay = 2000)
//    )
//    public void processUserLogAsync(SopUserLogsVo logVo, QwSopRuleTimeVO ruleTimeVO, List<QwSopTempSetting> tempSettings, CountDownLatch latch) {
//        try {
//            processUserLog(logVo, ruleTimeVO, tempSettings);
//        } catch (Exception e) {
//            log.error("处理用户日志 {} 时发生异常: {}", logVo.getId(), e.getMessage(), e);
//        } finally {
//            latch.countDown();
//        }
//    }
//
//
//    private void processUserLog(SopUserLogsVo logVo, QwSopRuleTimeVO ruleTimeVO, List<QwSopTempSetting> tempSettings) {
//        try {
//            LocalDate startDate = LocalDate.parse(logVo.getStartTime(), DATE_FORMATTER);
//            LocalDate currentDate = LocalDate.now();
////            LocalDate currentDate = LocalDate.parse("2024-12-25", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
//
//            long daysBetween = ChronoUnit.DAYS.between(startDate, currentDate);
//            int tempGap = ruleTimeVO.getTempGap();
//
//            if (tempGap <= 0) {
//                log.error("SOP ID {} 的 TempGap {} 无效，跳过处理。", logVo.getSopId(), tempGap);
//                return;
//            }
//
//            int intervalDay = (int) (daysBetween / tempGap);
//            if (intervalDay < 0 || intervalDay >= tempSettings.size()) {
//                log.info("用户日志 {} 的 intervalDay {} 超出 TempSettings 范围，跳过处理。", logVo.getId(), intervalDay);
//                return;
//            }
//
//            QwSopTempSetting selectedSetting = tempSettings.get(intervalDay);
//            List<QwSopTempSetting.Content> contents = selectedSetting.getContent();
//            if (contents == null || contents.isEmpty()) {
//                log.error("SOP ID {} 的 TempSetting 内容为空，跳过处理。", logVo.getSopId());
//                return;
//            }
//
//
//            //寻找时间
////            LocalDateTime currentTime = LocalDateTime.now();
//            LocalDateTime currentTime = LocalDateTime.of(2025, 2, 11,8 , 0);
//
//            // 先算好 60分钟后 ~ 再60分钟后的时间段
//            LocalDateTime startRangeFirst = currentTime.plusMinutes(60);
//
//            // 如果发现已经跨天
//            if (!startRangeFirst.toLocalDate().equals(currentDate)) {
//                // 更新 currentDate
//                currentDate = startRangeFirst.toLocalDate();
//
//                // 重新计算 daysBetween
//                daysBetween = ChronoUnit.DAYS.between(startDate, currentDate);
//                intervalDay = (int) (daysBetween / tempGap);
//
//                // 再次验证 intervalDay 是否在范围内
//                if (intervalDay < 0 || intervalDay >= tempSettings.size()) {
//                    log.info("跨天后，intervalDay={} 超出 TempSettings 范围，跳过。", intervalDay);
//                    return;
//                }
//
//                if (daysBetween % tempGap != 0) {
//                    log.error("天数差 {} 不是 tempGap {} 的整数倍，跳过操作,SopId {} ", daysBetween, tempGap,logVo.getSopId());
//                    return;
//                }
//
//                // 重新拿新的 “天” 的 Setting
//                selectedSetting = tempSettings.get(intervalDay);
//                contents = selectedSetting.getContent();
//                if (contents == null || contents.isEmpty()) {
//                    log.error("跨天-SOP ID {} 的 TempSetting 内容为空，跳过处理。", logVo.getSopId());
//                    return;
//                }
//            }
//
//
//            // 只有整倍数才做事
//            if (daysBetween % tempGap != 0) {
//                log.error("天数差 {} 不是 tempGap {} 的整数倍，跳过操作,SopId {} ", daysBetween, tempGap,logVo.getSopId());
//                return;
//            }
//
//
//            for (QwSopTempSetting.Content content : contents) {
//                try {
//
//                    LocalTime elementLocalTime = LocalTime.parse(content.getTime());
//                    LocalDateTime elementDateTime = LocalDateTime.of(currentTime.toLocalDate(), elementLocalTime);
//
//                    // 动态调整 elementDateTime 的日期
//                    if (elementLocalTime.isBefore(currentTime.toLocalTime())) {
//                        elementDateTime = elementDateTime.plusDays(1);
//                    }
//
//                    LocalDateTime startRange = currentTime.plusMinutes(60);
//                    LocalDateTime endRange = startRange.plusMinutes(60);
//
//                    // 跨天逻辑修正：仅当 startRange 的时间晚于 endRange 的时间时调整
//                    if (startRange.toLocalTime().isAfter(endRange.toLocalTime())
//                            && startRange.toLocalDate().equals(endRange.toLocalDate())) {
//                        endRange = endRange.plusDays(1); // 将 endRange 调整为第二天
//                    }
//                    if (!elementDateTime.isBefore(startRange) && elementDateTime.isBefore(endRange)) {
//
//                        // 如果时间差在目标范围内，更新记录
//                        // 组合年月日和element的时间
//                        LocalDate targetDate = startDate.plusDays(intervalDay * tempGap);
//
//                        // 将 targetDate 和 elementTime 组合成 LocalDateTime
//                        LocalDateTime dateTime = LocalDateTime.of(targetDate, elementLocalTime);
//
//                        // 将 LocalDateTime 转换为 Date
//                        Date sendTime = Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant());
//
//                        SopUserLogsInfo userLogsInfo=new SopUserLogsInfo();
//                        userLogsInfo.setSopId(logVo.getSopId());
//                        userLogsInfo.setUserLogsId(logVo.getId());
//
//                        List<SopUserLogsInfo> sopUserLogsInfos = sopUserLogsInfoMapper.selectSopUserLogsInfoList(userLogsInfo);
//
//                        insertSopUserLogs(sopUserLogsInfos, logVo, sendTime, ruleTimeVO, content);
//
//                    }
//                } catch (Exception e) {
//                    log.error("解析模板内容 {} 失败: {}", content.getTime(), e.getMessage(), e);
//                }
//            }
//
//        } catch (Exception e) {
//            log.error("解析解析模板 {} 失败: {}", logVo.getStartTime(), e.getMessage(), e);
//        }
//    }
//
//
//
//
//    private void insertSopUserLogs(List<SopUserLogsInfo> sopUserLogsInfos, SopUserLogsVo logVo, Date sendTime,
//                                   QwSopRuleTimeVO ruleTimeVO, QwSopTempSetting.Content content) {
//        String formattedSendTime = sendTime.toInstant()
//                .atZone(ZoneId.systemDefault())
//                .format(DATE_TIME_FORMATTER);
//        int type = content.getType();
//        Integer courseId = content.getCourseId();
//        Integer videoId = content.getVideoId();
//
//        String[] userKey = logVo.getUserId().split("\\|");
//        if (userKey.length < 3) {
//            log.error("用户 ID {} 格式不正确，跳过处理。", logVo.getUserId());
//            return;
//        }
//        String qwUserId = userKey[0].trim();
//        String companyUserId = userKey[1].trim();
//        String companyId = userKey[2].trim();
//
//        //生成语音
//        List<QwSopTempSetting.Content.Setting> setting = content.getSetting();
//        for (QwSopTempSetting.Content.Setting st : setting) {
//            if (st.getContentType().equals("7")){
//                try {
//                    AudioVO audioVO = AudioUtils.transferAudioSilkFromText(st.getValue(), Long.valueOf(companyUserId), false);
//                    st.setVoiceUrl(audioVO.getUrl());
//                    st.setVoiceDuration(audioVO.getDuration()+"");
//                }catch (Exception e){
//                    log.info("音频生成失败-: "+companyUserId);
//                }
//            }
//        }
//
//        // 处理每个 externalContactId
//        sopUserLogsInfos.forEach(contactId -> {
//            try {
//                String externalId = contactId.getExternalId().toString();
//                String externalUserName = contactId.getExternalUserName();
//                Long fsUserId = contactId.getFsUserId();
//                QwSopLogs sopLogs = createBaseLog(formattedSendTime, logVo, ruleTimeVO, contactId.getExternalContactId(), externalUserName, fsUserId);
//                handleLogBasedOnType(sopLogs, content, logVo, sendTime, courseId, videoId,
//                        type, qwUserId, companyUserId, companyId, externalId);
//            } catch (Exception e) {
//                log.error("处理 externalContactId {} 时发生异常: {}", contactId, e.getMessage(), e);
//            }
//        });
//    }
//
//
//
//    private QwSopLogs createBaseLog(String formattedSendTime, SopUserLogsVo logVo,
//                                    QwSopRuleTimeVO ruleTimeVO, String externalId,
//                                    String externalUserName, Long fsUserId) {
//        QwSopLogs sopLogs = new QwSopLogs();
//        sopLogs.setSendTime(formattedSendTime);
//        sopLogs.setQwUserid(logVo.getQwUserId());
//        sopLogs.setCorpId(logVo.getCorpId());
//        sopLogs.setLogType(ruleTimeVO.getType());
//        sopLogs.setSendType(ruleTimeVO.getSendType());
//        sopLogs.setSendStatus(3L);
//        sopLogs.setReceivingStatus(0L);
//
//        String[] userKey = logVo.getUserId().split("\\|");
//        sopLogs.setCompanyId(Long.valueOf(userKey[2].trim()));
//        sopLogs.setSopId(logVo.getSopId());
//
//        sopLogs.setExternalUserId(externalId);
//        sopLogs.setExternalUserName(externalUserName);
//        sopLogs.setFsUserId(fsUserId);
//
//        return sopLogs;
//    }
//
//    private void handleLogBasedOnType(QwSopLogs sopLogs, QwSopTempSetting.Content content,
//                                      SopUserLogsVo logVo, Date sendTime, Integer courseId,
//                                      Integer videoId, int type, String qwUserId,
//                                      String companyUserId, String companyId, String externalId) {
//        switch (type) {
//            case 1:
//                handleNormalMessage(sopLogs, content,companyUserId);
//                break;
//            case 2:
//                handleCourseMessage(sopLogs, content, logVo, sendTime, courseId, videoId,
//                        qwUserId, companyUserId, companyId, externalId);
//                break;
//            case 3:
//                handleOrderMessage(sopLogs, content);
//                break;
//            case 4:
//                handleAIMessage(sopLogs, content);
//                break;
//            default:
//                log.error("未知的消息类型 {}，跳过处理。", type);
//                break;
//        }
//    }
//
//    private void handleNormalMessage(QwSopLogs sopLogs, QwSopTempSetting.Content content,String companyUserId) {
//
//        sopLogs.setContentJson(JSON.toJSONString(content));
//        enqueueQwSopLogs(sopLogs);
//    }
//
//    private void handleAIMessage(QwSopLogs sopLogs, QwSopTempSetting.Content content) {
//        sopLogs.setContentJson(JSON.toJSONString(content));
//        sopLogs.setSort(3);
//        enqueueQwSopLogs(sopLogs);
//    }
//
//    private void handleCourseMessage(QwSopLogs sopLogs, QwSopTempSetting.Content content,
//                                     SopUserLogsVo logVo, Date sendTime, Integer courseId,
//                                     Integer videoId, String qwUserId, String companyUserId,
//                                     String companyId, String externalId) {
//        // 深拷贝 Content 对象，避免使用 JSON
//        QwSopTempSetting.Content clonedContent = deepCopyContent(content);
//        if (clonedContent == null) {
//            log.error("Failed to clone content, skipping handleCourseMessage.");
//            return;
//        }
//
////
////        Integer courseType = clonedContent.getCourseType();
//
//        List<QwSopTempSetting.Content.Setting> settings = clonedContent.getSetting();
//        if (settings == null || settings.isEmpty()) {
//            log.error("Cloned content settings are empty, skipping.");
//            return;
//        }
//
//
//        // 顺序处理每个 Setting，避免过多的并行导致线程开销
//        for (QwSopTempSetting.Content.Setting setting : settings) {
//            if ("1".equals(setting.getIsBindUrl())&&("3".equals(setting.getContentType())||"1".equals(setting.getContentType()))) {
//                addWatchLogIfNeeded(sopLogs, videoId, courseId, sendTime, qwUserId, companyUserId, companyId, externalId,logVo);
//                String sortLink = generateShortLink(setting, logVo, sendTime, courseId, videoId,
//                        qwUserId, companyUserId, companyId, externalId);
//                if (StringUtils.isNotEmpty(sortLink)) {
//                    if ("3".equals(setting.getContentType())) {
//                        setting.setLinkUrl(sortLink);
//                    } else {
//                        String currentValue = setting.getValue();
//                        if (currentValue == null) {
//                            setting.setValue(sortLink);
//                        } else {
//                            setting.setValue(currentValue + "\n" + sortLink);
//                        }
//                    }
//                } else {
//                    log.error("生成短链失败，跳过设置 URL。");
//                }
//            }
//        }
//        sopLogs.setContentJson(JSON.toJSONString(clonedContent));
//        enqueueQwSopLogs(sopLogs);
//    }
//
//    /**
//     * 深拷贝 Content 对象，避免使用 JSON 进行序列化和反序列化
//     */
//    private QwSopTempSetting.Content deepCopyContent(QwSopTempSetting.Content content) {
//        if (content == null) {
//            return null;
//        }
//        return content.clone();
//    }
//
//    private void handleOrderMessage(QwSopLogs sopLogs, QwSopTempSetting.Content content) {
//        sopLogs.setContentJson(JSON.toJSONString(content));
//        enqueueQwSopLogs(sopLogs);
//    }
//
//
//
//
//    private String generateShortLink(QwSopTempSetting.Content.Setting setting, SopUserLogsVo logVo, Date sendTime,
//                                Integer courseId, Integer videoId, String qwUserId,
//                                String companyUserId, String companyId, String externalId) {
//        // 获取缓存的配置
//        CourseConfig config;
//        synchronized(configLock) {
//            config = cachedCourseConfig;
//        }
//
//        if (config == null) {
//            log.error("CourseConfig is not loaded.");
//            return "";
//        }
//
//        // 手动创建 FsCourseLink 对象，避免使用 BeanUtils.copyProperties
//        FsCourseLink link = new FsCourseLink();
//        link.setCompanyId(Long.parseLong(companyId));
//        link.setQwUserId(qwUserId);
//        link.setCompanyUserId(Long.parseLong(companyUserId));
//        link.setVideoId(videoId.longValue());
//        link.setCorpId(logVo.getCorpId());
//        link.setCourseId(courseId.longValue());
//        link.setQwExternalId(Long.parseLong(externalId));
//        link.setLinkType(0); //正常链接
//
//        FsCourseRealLink courseMap = new FsCourseRealLink();
//        courseMap.setCompanyId(link.getCompanyId());
//        courseMap.setQwUserId(link.getQwUserId());
//        courseMap.setCompanyUserId(link.getCompanyUserId());
//        courseMap.setVideoId(link.getVideoId());
//        courseMap.setCorpId(link.getCorpId());
//        courseMap.setCourseId(link.getCourseId());
//        courseMap.setQwExternalId(link.getQwExternalId());
//        courseMap.setLinkType(0);
//
//        String courseJson = JSON.toJSONString(courseMap);
//        String realLinkFull = REAL_LINK_PREFIX + courseJson;
//        link.setRealLink(realLinkFull);
//
//        String randomString = generateRandomStringWithLock();
//        link.setLink(randomString);
//        link.setCreateTime(sendTime);
//
//        Integer expireDays = (setting.getExpiresDays() == null || setting.getExpiresDays() == 0)
//                ? config.getVideoLinkExpireDate()
//                : setting.getExpiresDays();
//
//        // 使用 Java 8 时间 API 计算过期时间
//        LocalDateTime sendDateTime = sendTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
//        LocalDateTime expireDateTime = sendDateTime.plusDays(expireDays-1);
//        expireDateTime = expireDateTime.toLocalDate().atTime(23, 59, 59);
//        Date updateTime = Date.from(expireDateTime.atZone(ZoneId.systemDefault()).toInstant());
//        link.setUpdateTime(updateTime);
//
//        // 从缓存中随机选择一个域名
//        FsCourseDomainName fsCourseDomainName;
//        if (cachedDomainNames == null || cachedDomainNames.isEmpty()) {
//            log.error("No domain names available for short link generation.");
//            return "";
//        }
//
//        int randomIndex = ThreadLocalRandom.current().nextInt(cachedDomainNames.size());
//        fsCourseDomainName = cachedDomainNames.get(randomIndex);
//
//        String sortLink = "https://" + fsCourseDomainName.getDomainName() + "/s/" + link.getLink();
//        enqueueCourseLink(link);
//        return sortLink;
//    }
//
//
//    private void addWatchLogIfNeeded(QwSopLogs sopLogs, Integer videoId, Integer courseId,
//                                     Date sendTime, String qwUserId, String companyUserId,
//                                     String companyId, String externalId,SopUserLogsVo logsVo) {
//        FsCourseWatchLog watchLog = new FsCourseWatchLog();
//        watchLog.setVideoId(videoId != null ? videoId.longValue() : null);
//        watchLog.setQwExternalContactId(externalId != null ? Long.valueOf(externalId) : null);
//        watchLog.setSendType(2);
//        watchLog.setQwUserId(qwUserId);
//        watchLog.setSopId(sopLogs.getSopId());
//        watchLog.setDuration(0L);
//        watchLog.setCourseId(courseId != null ? courseId.longValue() : null);
//        watchLog.setCompanyUserId(companyUserId != null ? Long.valueOf(companyUserId) : null);
//        watchLog.setCompanyId(companyId != null ? Long.valueOf(companyId) : null);
//        watchLog.setCreateTime(convertStringToDate(sopLogs.getSendTime(),"yyyy-MM-dd HH:mm:ss"));
//        watchLog.setUpdateTime(new Date());
//        watchLog.setLogType(3);
//        watchLog.setUserId(sopLogs.getFsUserId());
//        watchLog.setCampPeriodTime(convertStringToDate(logsVo.getStartTime(),"yyyy-MM-dd"));
//        enqueueWatchLog(watchLog);
//    }
//
//    /**
//     * 时间字符串转Date时间
//     * @param dateString
//     * @return
//     */
//    public static Date convertStringToDate(String dateString,String pattern) {
//        if (dateString == null || dateString.isEmpty()) {
//            return null;
//        }
//        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
//        LocalDateTime localDateTime;
//        LocalDate localDate;
//        // 先解析成 LocalDate（只含年月日）
//        if (pattern.equals("yyyy-MM-dd")){
//            // 先解析成 LocalDate（只含年月日）
//            localDate = LocalDate.parse(dateString, formatter);
//            // 将 LocalDate 转为当天 00:00:00 的 LocalDateTime
//            localDateTime = localDate.atStartOfDay();
//        }else {
//            localDateTime = LocalDateTime.parse(dateString, formatter);
//        }
//        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
//    }
//
//
//    /**
//     * 将 QwSopLogs 放入队列
//     */
//    private void enqueueQwSopLogs(QwSopLogs sopLogs) {
//        try {
//            boolean offered = qwSopLogsQueue.offer(sopLogs, 5, TimeUnit.SECONDS);
//            if (!offered) {
//                log.error("QwSopLogs 队列已满，无法添加日志: {}", JSON.toJSONString(sopLogs));
//                // 处理队列已满的情况，例如记录到失败队列或持久化存储
//            }
//        } catch (InterruptedException e) {
//            Thread.currentThread().interrupt();
//            log.error("插入 QwSopLogs 队列时被中断: {}", e.getMessage(), e);
//        }
//    }
//
//    /**
//     * 将 FsCourseWatchLog 放入队列
//     */
//    private void enqueueWatchLog(FsCourseWatchLog watchLog) {
//        try {
//            boolean offered = watchLogsQueue.offer(watchLog, 5, TimeUnit.SECONDS);
//            if (!offered) {
//                log.error("FsCourseWatchLog 队列已满，无法添加日志: {}", JSON.toJSONString(watchLog));
//                // 处理队列已满的情况，例如记录到失败队列或持久化存储
//            }
//        } catch (InterruptedException e) {
//            Thread.currentThread().interrupt();
//            log.error("插入 FsCourseWatchLog 队列时被中断: {}", e.getMessage(), e);
//        }
//    }
//
//    /**
//     * 将 FsCourseWatchLog 放入队列
//     */
//    private void enqueueCourseLink(FsCourseLink courseLink) {
//        try {
//            boolean offered = linkQueue.offer(courseLink, 5, TimeUnit.SECONDS);
//            if (!offered) {
//                log.error("FsCourseLink 队列已满，无法添加日志: {}", JSON.toJSONString(courseLink));
//                // 处理队列已满的情况，例如记录到失败队列或持久化存储
//            }
//        } catch (InterruptedException e) {
//            Thread.currentThread().interrupt();
//            log.error("插入 FsCourseLink 队列时被中断: {}", e.getMessage(), e);
//        }
//    }
//
//    /**
//     * 消费 QwSopLogs 队列并进行批量插入
//     */
//    private void consumeQwSopLogs() {
//        List<QwSopLogs> batch = new ArrayList<>(BATCH_SIZE);
//        while (running || !qwSopLogsQueue.isEmpty()) {
//            try {
//                QwSopLogs log = qwSopLogsQueue.poll(1, TimeUnit.SECONDS);
//                if (log != null) {
//                    batch.add(log);
//                }
//                if (batch.size() >= BATCH_SIZE || (!batch.isEmpty() && log == null)) {
//                    if (!batch.isEmpty()) {
//                        batchInsertQwSopLogs(new ArrayList<>(batch));
//                        batch.clear();
//                    }
//                }
//            } catch (InterruptedException e) {
//                Thread.currentThread().interrupt();
//                log.error("QwSopLogs 消费线程被中断: {}", e.getMessage(), e);
//            }
//        }
//
//        // 处理剩余的数据
//        if (!batch.isEmpty()) {
//            batchInsertQwSopLogs(batch);
//        }
//    }
//
//    /**
//     * 消费 FsCourseWatchLog 队列并进行批量插入
//     */
//    private void consumeCourseLink() {
//        List<FsCourseLink> batch = new ArrayList<>(BATCH_SIZE);
//        while (running || !linkQueue.isEmpty()) {
//            try {
//                FsCourseLink courseLink = linkQueue.poll(1, TimeUnit.SECONDS);
//                if (courseLink != null) {
//                    batch.add(courseLink);
//                }
//                if (batch.size() >= BATCH_SIZE || (!batch.isEmpty() && courseLink == null)) {
//                    if (!batch.isEmpty()) {
//                        batchInsertFsCourseLink(new ArrayList<>(batch));
//                        batch.clear();
//                    }
//                }
//            } catch (InterruptedException e) {
//                Thread.currentThread().interrupt();
//                log.error("FsCourseLink 消费线程被中断: {}", e.getMessage(), e);
//            }
//        }
//
//        // 处理剩余的数据
//        if (!batch.isEmpty()) {
//            batchInsertFsCourseLink(batch);
//        }
//    }
//
//    /**
//     * 消费 FsCourseWatchLog 队列并进行批量插入
//     */
//    private void consumeWatchLogs() {
//        List<FsCourseWatchLog> batch = new ArrayList<>(BATCH_SIZE);
//        while (running || !watchLogsQueue.isEmpty()) {
//            try {
//                FsCourseWatchLog watchLog = watchLogsQueue.poll(1, TimeUnit.SECONDS);
//                if (watchLog != null) {
//                    batch.add(watchLog);
//                }
//                if (batch.size() >= BATCH_SIZE || (!batch.isEmpty() && watchLog == null)) {
//                    if (!batch.isEmpty()) {
//                        batchInsertFsCourseWatchLogs(new ArrayList<>(batch));
//                        batch.clear();
//                    }
//                }
//            } catch (InterruptedException e) {
//                Thread.currentThread().interrupt();
//                log.error("FsCourseWatchLog 消费线程被中断: {}", e.getMessage(), e);
//            }
//        }
//
//        // 处理剩余的数据
//        if (!batch.isEmpty()) {
//            batchInsertFsCourseWatchLogs(batch);
//        }
//    }
//
//    /**
//     * 批量插入 QwSopLogs
//     */
//    @Transactional
//    @Retryable(
//            value = { Exception.class },
//            maxAttempts = 3,
//            backoff = @Backoff(delay = 2000)
//    )
//    public void batchInsertQwSopLogs(List<QwSopLogs> logsToInsert) {
//        try {
//            qwSopLogsService.batchInsertQwSopLogs(logsToInsert);
//            log.info("批量插入 QwSopLogs 完成，共插入 {} 条记录。", logsToInsert.size());
//        } catch (Exception e) {
//            log.error("批量插入 QwSopLogs 失败: {}", e.getMessage(), e);
//            // 可选：将失败的数据记录到失败队列或持久化存储以便后续重试
//        }
//    }
//
//    /**
//     * 批量插入 FsCourseWatchLog
//     */
//    @Transactional
//    @Retryable(
//            value = { Exception.class },
//            maxAttempts = 3,
//            backoff = @Backoff(delay = 2000)
//    )
//    public void batchInsertFsCourseWatchLogs(List<FsCourseWatchLog> watchLogsToInsert) {
//        try {
//            fsCourseWatchLogMapper.insertFsCourseWatchLogBatch(watchLogsToInsert);
//            log.info("批量插入 FsCourseWatchLog 完成，共插入 {} 条记录。", watchLogsToInsert.size());
//        } catch (Exception e) {
//            log.error("批量插入 FsCourseWatchLog 失败: {}", e.getMessage(), e);
//            // 可选：将失败的数据记录到失败队列或持久化存储以便后续重试
//        }
//    }
//
//
//    /**
//     * 批量插入 FsCourseLink
//     */
//    @Transactional
//    @Retryable(
//            value = { Exception.class },
//            maxAttempts = 3,
//            backoff = @Backoff(delay = 2000)
//    )
//    public void batchInsertFsCourseLink(List<FsCourseLink> courseLinkToInsert) {
//        try {
//            fsCourseLinkMapper.insertFsCourseLinkBatch(courseLinkToInsert);
//            log.info("批量插入 FsCourseLink 完成，共插入 {} 条记录。", courseLinkToInsert.size());
//        } catch (Exception e) {
//            log.error("批量插入 FsCourseLink 失败: {}", e.getMessage(), e);
//            // 可选：将失败的数据记录到失败队列或持久化存储以便后续重试
//        }
//    }
//
//}
