package com.fs.app.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fs.common.core.redis.RedisCache;
import com.fs.common.exception.base.BaseException;
import com.fs.common.utils.StringUtils;
import com.fs.common.utils.date.DateUtil;
import com.fs.common.utils.spring.SpringUtils;
import com.fs.company.domain.CompanyMiniapp;
import com.fs.company.service.ICompanyMiniappService;
import com.fs.course.domain.FsCoursePlaySourceConfig;
import com.fs.course.domain.FsCourseWatchLog;
import com.fs.course.domain.FsUserCourseVideo;
import com.fs.course.mapper.FsCoursePlaySourceConfigMapper;
import com.fs.course.mapper.FsUserCourseVideoMapper;
import com.fs.course.service.IFsCoursePlaySourceConfigService;
import com.fs.course.service.IFsCourseWatchLogService;
import com.fs.his.domain.FsUser;
import com.fs.his.mapper.FsUserMapper;
import com.fs.ipad.IpadSendUtils;
import com.fs.ipad.vo.*;
import com.fs.live.domain.LiveWatchLog;
import com.fs.live.mapper.LiveWatchLogMapper;
import com.fs.qw.domain.QwExternalContact;
import com.fs.qw.domain.QwUser;
import com.fs.qw.domain.QwUserVideo;
import com.fs.qw.mapper.QwExternalContactMapper;
import com.fs.qw.mapper.QwUserMapper;
import com.fs.qw.service.IQwUserService;
import com.fs.qw.service.IQwUserVideoService;
import com.fs.qw.vo.QwSopCourseFinishTempSetting;
import com.fs.qwApi.param.QwExternalContactHParam;
import com.fs.sop.domain.QwSopLogs;
import com.fs.sop.service.IQwSopLogsService;
import com.fs.sop.service.impl.QwSopLogsServiceImpl;
import com.fs.wxwork.dto.*;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@AllArgsConstructor
public class IpadSendServer {

    private final QwUserMapper qwUserMapper;
    private final IQwUserService qwUserService;
    private final IpadSendUtils ipadSendUtils;
    private final IQwSopLogsService qwSopLogsService;
    private final QwExternalContactMapper qwExternalContactMapper;
    private final IFsCourseWatchLogService watchLogService;
    private final IQwUserVideoService qwUserVideoService;
    private final RedisCache redisCache;
    private final ICompanyMiniappService companyMiniappService;
    private final IFsCoursePlaySourceConfigService playSourceConfigService;
    private final FsUserMapper fsUserMapper;
    private final FsUserCourseVideoMapper fsUserCourseVideoMapper;


    private static final List<String> PROJECT_NAMES = Arrays.asList("济南联志健康", "北京存在文化","宽益堂");
    private final LiveWatchLogMapper liveWatchLogMapper;

    private void sendMiniProgram(BaseVo vo, QwSopCourseFinishTempSetting.Setting content, Map<String, FsCoursePlaySourceConfig> miniMap, Long companyId) {
        // 发送参数原本的appid
        String appid = content.getMiniprogramAppid();
        // 判断销售工时ID不为空并且有小程序类型
        if(companyId != null && content.getMiniType() != null){
            // 获取销售公司下面绑定的主备小程序，并且根据当前应该发送的主备类型查询出数据
            List<CompanyMiniapp> listAll = companyMiniappService.list(new QueryWrapper<CompanyMiniapp>().eq("company_id", companyId));
            List<CompanyMiniapp> list = listAll.stream().filter(e -> e.getType().equals(content.getMiniType())).collect(Collectors.toList());
            // 判断当前绑定的最新的小程序，并且覆盖以前的值（可以达到实时替换小程序的功能）
            if(!list.isEmpty() && list.get(0) != null && StringUtils.isNotEmpty(list.get(0).getAppId())){
                appid = list.get(0).getAppId();
            }
            // 获取配置文件里面的项目名称
            String signProjectName = SpringUtils.getProperty("cloud_host.company_name");
            //区分新老用户，新用户发送备用小程序，老用户发送主小程序，TODO 需要使用的项目在参数里面加上
            if(PROJECT_NAMES.contains(signProjectName)){
                log.info("ID:{}, qwUserId:{}，externalId:{}，进入区分发小程序逻辑", vo.getId(), vo.getQwUserId(), vo.getExId());
                // 判断消息是否是群聊，不是群聊再进去，TODO 当权无法判断群聊是否可以发送对应的小程序
                if(!vo.isRoom()){
                    log.info("ID:{}, qwUserId:{}，externalId:{}，不是群聊", vo.getId(), vo.getQwUserId(), vo.getExId());
                    try {
                        // 获取当前外部联系人
                        QwExternalContact qwExternalContact = qwExternalContactMapper.selectOne(new LambdaQueryWrapper<QwExternalContact>().eq(QwExternalContact::getQwUserId,vo.getQwUserId()).eq(QwExternalContact::getExternalUserId,vo.getExId()).last(" limit 1"));
                        // 当前外部联系是否绑定用户数据，如果数据为空则是没看过小程序的新用户，不用去判断小程序，跳过判断
                        if(qwExternalContact.getFsUserId() != null){
                            // 根据用户绑定信息去查询用户信息
                            FsUser fsUser = fsUserMapper.selectFsUserByUserId(qwExternalContact.getFsUserId());
                            // 判断用户是否有看过其他的小程序多个
                            if(StringUtils.isNotEmpty(fsUser.getAppId())){
                                // 获取用户看过的小程序ID集合
                                List<String> miniAppList = Arrays.asList(fsUser.getAppId().split(","));
                                // 根据小程序ID查询小程序列表
                                List<FsCoursePlaySourceConfig> configList = playSourceConfigService.selectByAppIds(miniAppList);
                                // 过滤掉完全封禁(status=2)的小程序，只保留正常(status=0)和半封禁(status=1)的小程序
                                List<FsCoursePlaySourceConfig> availableList = configList.stream()
                                    .filter(e -> e.getStatus() == null || e.getStatus() != 2)
                                    .collect(Collectors.toList());
                                // 筛选出半封禁的小程序数据，得到这个数据然后优先发这个小程序
                                Optional<FsCoursePlaySourceConfig> optional = availableList.stream().filter(e -> e.getStatus() != null && e.getStatus() == 1).findFirst();
                                Optional<FsCoursePlaySourceConfig> optional2 = availableList.stream().filter(e -> e.getStatus() != null && e.getStatus() == 0).findFirst();
                                if(miniAppList.size() == 1){
                                    // 用户只看过一个小程序，检查是否可用
                                    if(!availableList.isEmpty()){
                                        appid = availableList.get(0).getAppid();
                                        log.info("ID:{}, qwUserId:{}，externalId:{}，判断看过一个小程序：{}", vo.getId(), vo.getQwUserId(), vo.getExId(), appid);
                                    }else{
                                        // 用户看过的小程序已完全封禁，使用备用小程序
                                        Optional<CompanyMiniapp> first = listAll.stream().filter(e -> e.getType() == 1).findFirst();
                                        if(first.isPresent()){
                                            appid = first.get().getAppId();
                                            log.info("ID:{}, qwUserId:{}，externalId:{}，看过的小程序已封禁，使用备用小程序:{}", vo.getId(), vo.getQwUserId(), vo.getExId(), appid);
                                        }
                                    }
                                }else{
                                    // 判断是否找到半封禁
                                    if(optional.isPresent()){
                                        // 找到半封禁并且在appid里面存在证明这个客户是打开过小程序，优先发送这个
                                        appid = optional.get().getAppid();
                                        log.info("ID:{}, qwUserId:{}，externalId:{}，找到半封禁小程序:{}", vo.getId(), vo.getQwUserId(), vo.getExId(), appid);
                                    }else if(optional2.isPresent()){
                                        appid = optional2.get().getAppid();
                                        log.info("ID:{}, qwUserId:{}，externalId:{}，找到正常小程序:{}", vo.getId(), vo.getQwUserId(), vo.getExId(), appid);
                                    }else{
                                        Optional<CompanyMiniapp> first = listAll.stream().filter(e -> e.getType() == 1).findFirst();
                                        // 查找备用小程序发送备用记录ID
                                        if(first.isPresent()){
                                            appid = first.get().getAppId();
                                            log.info("ID:{}, qwUserId:{}，externalId:{}，找到备用小程序:{}", vo.getId(), vo.getQwUserId(), vo.getExId(), appid);
                                        }else{
                                            log.info("ID:{}, qwUserId:{}，externalId:{}，没找到小程序:{}", vo.getId(), vo.getQwUserId(), vo.getExId(), appid);
                                        }
                                    }
                                }
                            }else{
                                // 获取用户的创建时间
                                LocalDateTime createTime = DateUtil.dateToLocalDateTime(fsUser.getCreateTime());
                                log.info("ID:{}, qwUserId:{}，externalId:{}，已绑定小程序，判断时间：{}", vo.getId(), vo.getQwUserId(), vo.getExId(), createTime);
                                // 这个时间是写死的，目前判断的芳华封禁的时间，可以更具项目调整
                                LocalDateTime lastTime = LocalDateTime.of(2025, 11, 10, 23, 59, 59);
                                // 判断客户创建时间是在这个之前还是之后
                                int listIndex = createTime.isAfter(lastTime) ? 1 : 0 ;
                                // 获取公司里面的主备小程序，根据用户创建时间来发送主备，如果创建时间大于上看的时间就发送备用小程序，如果小于就发送主要小程序
                                List<CompanyMiniapp> collect2 = listAll.stream().filter(e -> e.getType().equals(listIndex)).collect(Collectors.toList());
                                // 判断是否获取到了配置
                                if(!collect2.isEmpty() && collect2.get(0) != null && StringUtils.isNotEmpty(collect2.get(0).getAppId())){
                                    appid = collect2.get(0).getAppId();
                                    log.info("ID:{}, qwUserId:{}，externalId:{}，发送小程序：{}", vo.getId(), vo.getQwUserId(), vo.getExId(), appid);
                                }
                            }
                        }else{
                            log.info("ID:{}, qwUserId:{}，externalId:{}，未绑定小程序用户", vo.getId(), vo.getQwUserId(), vo.getExId());
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        log.error("6.输出外部联系人ID-------------->{}",vo.getExId());
                        log.error("7.数据异常----------------------》{}",e.getMessage());
                    }
                }
            }
        }
        FsCoursePlaySourceConfig courseMaConfig = miniMap.get(appid);
        if(courseMaConfig == null){
            List<CompanyMiniapp> list = companyMiniappService.list(new QueryWrapper<CompanyMiniapp>().eq("company_id", companyId).eq("type", 1));
            if(!list.isEmpty() && list.get(0) != null && StringUtils.isNotEmpty(list.get(0).getAppId())){
                courseMaConfig = miniMap.get(list.get(0).getAppId());
            }
        }
        if(courseMaConfig == null){
            throw new BaseException("未找到小程序配置：{}", appid);
        }
        // 小程序
        MiniProgramVo miniProgramVo = MiniProgramVo.builder()
                .desc(content.getMiniprogramTitle())
                .title(courseMaConfig.getName())
                .weappIconUrl(courseMaConfig.getImg())
                .imgUrl(content.getMiniprogramPicUrl())
                .username(courseMaConfig.getOriginalId() + "@app")
                .pagepath(content.getMiniprogramPage())
                .appid(courseMaConfig.getAppid())
                .build();
        miniProgramVo.setBase(vo);
        WxWorkResponseDTO<WxWorkSendAppMsgRespDTO> resp = ipadSendUtils.sendMiniProgram(miniProgramVo);
        if (resp.getErrcode() != 0) {
            log.debug("ID:{}-ipad接口请求返回异常：{}", vo.getId(), resp.getErrmsg());
            content.setSendStatus(2);
            content.setSendRemarks("发送失败：" + resp.getErrmsg());
        }
    }

    private void sendFile(BaseVo vo, QwSopCourseFinishTempSetting.Setting content) {
        FileVo fileVo = FileVo.builder()
                .url(content.getFileUrl())
                .fileName(content.getFileName())  // 传递文件名
                .build();
        fileVo.setBase(vo);
        WxWorkResponseDTO<WxwSendCDNFileMsgRespDTO> resp = ipadSendUtils.sendFile(fileVo);
        if (resp.getErrcode() != 0) {
            log.debug("ID:{}-ipad接口请求返回异常：{}", vo.getId(), resp.getErrmsg());
            content.setSendStatus(2);
            content.setSendRemarks("发送失败：" + resp.getErrmsg());
        }
    }

    public void sendTxt(BaseVo vo, QwSopCourseFinishTempSetting.Setting content) {
        TxtVo txtVo = TxtVo.builder().content(content.getValue()).build();
        txtVo.setBase(vo);
        WxWorkResponseDTO<WxWorkSendTextMsgRespDTO> resp = ipadSendUtils.sendTxt(txtVo);
        if (resp.getErrcode() != 0) {
            log.debug("ID:{}-ipad接口请求返回异常：{}", vo.getId(), resp.getErrmsg());
            content.setSendStatus(2);
            content.setSendRemarks("发送失败：" + resp.getErrmsg());
        }
    }

    public void sendImg(BaseVo vo, QwSopCourseFinishTempSetting.Setting content) {
        FileVo imgVo = FileVo.builder().url(content.getImgUrl()).build();
        imgVo.setBase(vo);
        WxWorkResponseDTO<WxwSendCDNImgMsgRespDTO> resp = ipadSendUtils.sendImg(imgVo);
        if (resp.getErrcode() != 0) {
            log.debug("ID:{}-ipad接口请求返回异常：{}", vo.getId(), resp.getErrmsg());
            content.setSendStatus(2);
            content.setSendRemarks("发送失败：" + resp.getErrmsg());
        }
    }

    public void sendLink(BaseVo vo, QwSopCourseFinishTempSetting.Setting content) {
        // 文本
        LinkVo linkVo = LinkVo.builder()
                .title(content.getLinkTitle())
                .content(content.getLinkDescribe())
                .url(content.getLinkUrl())
                .imgUrl(content.getLinkImageUrl())
                .build();
        linkVo.setBase(vo);
        WxWorkResponseDTO<WxwSendLinkMsgRespDTO> resp = ipadSendUtils.sendLink(linkVo);
        if (resp.getErrcode() != 0) {
            log.debug("ID:{}-ipad接口请求返回异常：{}", vo.getId(), resp.getErrmsg());
            content.setSendStatus(2);
            content.setSendRemarks("发送失败：" + resp.getErrmsg());
        }
    }

    public void sendVideo(BaseVo vo, QwSopCourseFinishTempSetting.Setting content) {
        FileVo videoVo = FileVo.builder()
                .url(content.getVideoUrl())
                .build();
        videoVo.setBase(vo);
        WxWorkResponseDTO<WxwSendCDNVideoMsgRespDTO> resp = ipadSendUtils.sendVideo(videoVo);
        if (resp.getErrcode() != 0) {
            log.debug("ID:{}-ipad接口请求返回异常：{}", vo.getId(), resp.getErrmsg());
            content.setSendStatus(2);
            content.setSendRemarks("发送失败：" + resp.getErrmsg());
        }
    }

    public void sendWxVideo(BaseVo vo, QwSopCourseFinishTempSetting.Setting content) {
        QwUserVideo qwUserVideo = qwUserVideoService.selectQwUserVideoById(content.getVideoId());
        WxVideoVo videoVo = WxVideoVo.builder()
                .coverUrl(qwUserVideo.getCoverUrl())
                .thumbUrl(qwUserVideo.getThumbUrl())
                .avatar(qwUserVideo.getAvatar())
                .nickname(qwUserVideo.getNickName())
                .desc(qwUserVideo.getDesc())
                .url(qwUserVideo.getUrl())
                .extras(qwUserVideo.getExtras())
                .objectId(qwUserVideo.getObjectId())
                .objectNonceId(qwUserVideo.getObjectNonceId())
                .build();
        videoVo.setBase(vo);
        WxWorkResponseDTO<WxwSendVideoNumberRespDTO> resp = ipadSendUtils.sendWxVideo(videoVo);
        if (resp.getErrcode() != 0) {
            log.debug("ID:{}-ipad接口请求返回异常：{}", vo.getId(), resp.getErrmsg());
            content.setSendStatus(2);
            content.setSendRemarks("发送失败：" + resp.getErrmsg());
        }
    }


    public void sendTxtAtMsg(BaseVo vo) {
        WxSendTextAtMsgTwoDTO dto = new WxSendTextAtMsgTwoDTO();
        List<WxSendTextAtMsgTwoDTO.Contentva> contentvaList = new ArrayList<>();
        WxSendTextAtMsgTwoDTO.Contentva contentva = new WxSendTextAtMsgTwoDTO.Contentva();
        contentva.setMsgtype(5);
        contentva.setVid(0);
        contentvaList.add(contentva);
        dto.setContentva(contentvaList);
        dto.setBase(vo);
        dto.setUuid(vo.getUuid());
        dto.setSend_userid(ipadSendUtils.userIds(vo));
        dto.setIsRoom(true);
       ipadSendUtils.sendTxtAtMsgVo(dto, vo.getServerId() ,vo.getId());
    }
    public void sendVoice(BaseVo vo, QwSopCourseFinishTempSetting.Setting content) {
        if (StringUtils.isEmpty(content.getVoiceUrl()) || StringUtils.isEmpty(content.getVoiceDuration())) {
            log.debug("语音未生成无法发送，转文字发送：{}", vo);
            sendTxt(vo, content);
            return;
        }
        FileVo voiceVo = FileVo.builder()
                .url(content.getVoiceUrl())
                .voiceTime(Integer.parseInt(content.getVoiceDuration()))
                .build();
        voiceVo.setBase(vo);
        WxWorkResponseDTO<WxwSendCDNVoiceMsgRespDTO> resp = ipadSendUtils.sendVoice(voiceVo);
        if (resp.getErrcode() != 0) {
            log.debug("ID:{}-ipad接口请求返回异常：{}", vo.getId(), resp.getErrmsg());
            content.setSendStatus(2);
            content.setSendRemarks("发送失败：" + resp.getErrmsg());
        }
    }

    public boolean isSend(QwUser qwUser, BaseVo parentVo) {
        // 判断企微发送方式是否是ipad
        if (qwUser.getSendMsgType() == 0) {
            log.debug("发送方式是侧边栏企微用户：ID：{} 名称：{}", qwUser.getId(), qwUser.getQwUserName());
            return false;
        }
        // 判断是否信息准确
        if (org.springframework.util.StringUtils.isEmpty(qwUser.getUid())) {
            log.debug("企微用户：ID：{} 名称：{}", qwUser.getId(), qwUser.getQwUserName());
            return false;
        }
        // 是否已经授权服务器地址
        if (qwUser.getServerId() == null) {
            log.debug("企微用户：ID：{} 名称：{} 未绑定AI主机", qwUser.getId(), qwUser.getQwUserName());
            return false;
        }
        // ipad状态是否是登录状态
        if (qwUser.getIpadStatus() == 0) {
            log.debug("企微用户：ID：{} 名称：{} 未登录uid:{}，serveID:{}", qwUser.getId(), qwUser.getQwUserName(), qwUser.getUid(), qwUser.getServerId());
            return false;
        }
        // 更新信息使用的类
        QwUser updateQwUser = new QwUser();
        try {
            // 调用ipad接口判断是否真实登录
            WxLoginResp login = ipadSendUtils.isLogin(qwUser.getUid(), qwUser.getServerId());
            if (login.getLoginType() == 0) {
                updateQwUser.setId(qwUser.getId());
                updateQwUser.setRemark("AI未初始化");
                updateQwUser.setIpadStatus(0);
                qwUserMapper.updateById(updateQwUser);
                return false;
            }
            if (login.getLoginType() == 1) {
                updateQwUser.setId(qwUser.getId());
                updateQwUser.setRemark("未登录");
                updateQwUser.setIpadStatus(0);
                qwUserMapper.updateById(updateQwUser);
                qwUserService.atMsg(qwUser, "掉线提醒（未登录）");
                return false;
            }
            if (!login.getUser_info().isLogin()) {
                updateQwUser.setId(qwUser.getId());
                updateQwUser.setRemark("登录状态异常");
                updateQwUser.setIpadStatus(0);
                qwUserMapper.updateById(updateQwUser);
                qwUserService.atMsg(qwUser, "掉线提醒（登录异常）");
                return false;
            }
            parentVo.setCorpId(login.getUser_info().getObject().getCorp_id());
            log.debug("QwUserID:{}, AI主机信息：{}", qwUser.getId(), login);
        } catch (Exception e) {
            updateQwUser.setId(qwUser.getId());
            updateQwUser.setRemark("登录状态异常：" + e.getMessage());
            updateQwUser.setIpadStatus(0);
            qwUserMapper.updateById(updateQwUser);
            qwUserService.atMsg(qwUser, "掉线提醒（登录信息异常，请联系管理员："+e.getMessage()+"）");
            return false;
        }

        return true;
    }

    public boolean isSendLogs(QwSopLogs qwSopLogs, QwSopCourseFinishTempSetting setting, QwUser qwUser) {
        if(qwSopLogs.getSendStatus() != 3){
            log.info("状态异常不发送：{}, LOGID: {}", qwUser.getQwUserName(), qwSopLogs.getId());
            return false;
        }
        if(redisCache.getCacheObject("qw:user:id:" + qwUser.getId()) != null){
            log.info("频率异常不发送：{}", qwUser.getQwUserName());
            return false;
        }

        boolean noSop = qwSopLogs.getSendType() != 3 && qwSopLogs.getSendType() != 7;

        if (qwSopLogs.getExpiryTime() == null && noSop) {
            // 作废消息
            log.warn("SOP_LOG_ID:{}, SOP任务被删除", qwSopLogs.getId());
            qwSopLogsService.updateQwSopLogsByWatchLogType(qwSopLogs.getId(), "SOP任务被删除");
            return false;
        }

        LocalDateTime sendTime = DateUtil.stringToLocalDateTime(qwSopLogs.getSendTime());
        LocalDateTime expiryDateTime;

        // 判断是否过期
        if(qwSopLogs.getSendType() == 3 || qwSopLogs.getSendType() == 7){
            expiryDateTime = sendTime.plusHours(12);
        }else{
            expiryDateTime = sendTime.plusHours(qwSopLogs.getExpiryTime());
        }

        if (LocalDateTime.now().isAfter(expiryDateTime)  ) {
            // 作废消息
            log.warn("SOP_LOG_ID:{}, 已过期，不发送", qwSopLogs.getId());
            qwSopLogsService.updateQwSopLogsByWatchLogType(qwSopLogs.getId(), "已过期，不发送");
            return false;
        }

        if (setting.getCourseType() == null && noSop && setting.getType() == 2) {
            log.warn("SOP_LOG_ID:{}, 模板未选消息类型，不发送", qwSopLogs.getId());
            qwSopLogsService.updateQwSopLogsByWatchLogType(qwSopLogs.getId(), "模板未选消息类型，不发送");
            return false;
        }

        // 查询视频是否下架
        if(setting.getVideoId()!= null){
            FsUserCourseVideo video = fsUserCourseVideoMapper.selectFsUserCourseVideoByVideoId( setting.getVideoId().longValue());
            if(video != null){
                if(video.getIsOnPut()!=null && video.getIsOnPut() == 1){
                    log.warn("SOP_LOG_ID:{}, 视频已下架，不发送", qwSopLogs.getId());
                    qwSopLogsService.updateQwSopLogsByWatchLogType(qwSopLogs.getId(), "视频已下架，不发送");
                    return false;
                }
            }
        }

        if (qwSopLogs.getSendType() != 6 && noSop) {
            // 客户的信息
//            QwExternalContactHParam contactHParam = new QwExternalContactHParam();
//            contactHParam.setUserId(qwUser.getQwUserId().trim());
//            contactHParam.setExternalUserId(qwSopLogs.getExternalUserId().trim());
//            contactHParam.setCorpId(qwUser.getCorpId().trim());
            Integer courseType = setting.getCourseType();
            if (setting.getType() == 2 && courseType != 0) {// 课程消息，进行复杂的条件判断
//                log.debug("企微查询：{}", contactHParam);
//                Long qwExternalContactId = qwExternalContactMapper.getQwExternalContactId(contactHParam);
                FsCourseWatchLog watchLog = watchLogService.getWatchCourseLogVideoBySop(
                        setting.getVideoId().longValue(),
                        String.valueOf(qwUser.getId()),
                        qwSopLogs.getExternalId()
                );
                log.debug("ID:{}-看课记录参数：videoID:{}， qwUserID:{}， extID:{}", qwSopLogs.getId(), setting.getVideoId().longValue(), qwUser.getId(), qwSopLogs.getExternalId());
                log.debug("ID:{}-看课记录：{}", qwSopLogs.getId(), watchLog);
                String logId = qwSopLogs.getId();
                if (watchLog != null) {
                    //新逻辑
                    if (!QwSopLogsServiceImpl.isCourseTypeValid(courseType, watchLog.getLogType())) {
                        // 作废消息
                        log.warn("SOP_LOG_ID:{}, 看课状态未满足，不发送", qwSopLogs.getId());
                        qwSopLogsService.updateQwSopLogsByWatchLogType(logId, "看课状态未满足，不发送");
                        return false;
                    }
                } else {
                    log.warn("SOP_LOG_ID:{}, 无观看记录，不发送", qwSopLogs.getId());
                    qwSopLogsService.updateQwSopLogsByWatchLogType(logId, "无观看记录，不发送");
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 直播间判定消息
     * @param qwSopLogs
     * @param setting
     * @param qwUser
     * @return
     */
    public boolean isSendLogsLive(QwSopLogs qwSopLogs, QwSopCourseFinishTempSetting setting, QwUser qwUser){
        if(qwSopLogs.getSendStatus() != 3){
            log.info("直播状态异常不发送：{}, LOGID: {}", qwUser.getQwUserName(), qwSopLogs.getId());
            return false;
        }
        if(redisCache.getCacheObject("qw:user:id:" + qwUser.getId()) != null){
            log.info("直播频率异常不发送：{}", qwUser.getQwUserName());
            return false;
        }

        boolean noSop = qwSopLogs.getSendType() != 3 && qwSopLogs.getSendType() != 7;

        if (qwSopLogs.getExpiryTime() == null && noSop) {
            // 作废消息
            log.warn("直播SOP_LOG_ID:{}, 直播SOP任务被删除", qwSopLogs.getId());
            qwSopLogsService.updateQwSopLogsByWatchLogType(qwSopLogs.getId(), "直播SOP任务被删除");
            return false;
        }

        LocalDateTime sendTime = DateUtil.stringToLocalDateTime(qwSopLogs.getSendTime());
        LocalDateTime expiryDateTime;

        // 判断是否过期
        if(qwSopLogs.getSendType() == 3 || qwSopLogs.getSendType() == 7){
            expiryDateTime = sendTime.plusHours(12);
        }else{
            expiryDateTime = sendTime.plusHours(qwSopLogs.getExpiryTime());
        }

        if (LocalDateTime.now().isAfter(expiryDateTime)) {
            // 作废消息
            log.warn("直播SOP_LOG_ID:{}, 已过期，不发送", qwSopLogs.getId());
            qwSopLogsService.updateQwSopLogsByWatchLogType(qwSopLogs.getId(), "已过期，不发送");
            return false;
        }

        if (setting.getCourseType() == null && noSop && setting.getType() == 2) {
            log.warn("直播SOP_LOG_ID:{}, 模板未选消息类型，不发送", qwSopLogs.getId());
            qwSopLogsService.updateQwSopLogsByWatchLogType(qwSopLogs.getId(), "直播模板未选消息类型，不发送");
            return false;
        }

        // 查询视频是否下架
//        if(setting.getVideoId()!= null){
//            FsUserCourseVideo video = fsUserCourseVideoMapper.selectFsUserCourseVideoByVideoId( setting.getVideoId().longValue());
//            if(video != null){
//                if(video.getIsOnPut()!=null && video.getIsOnPut() == 1){
//                    log.warn("SOP_LOG_ID:{}, 视频已下架，不发送", qwSopLogs.getId());
//                    qwSopLogsService.updateQwSopLogsByWatchLogType(qwSopLogs.getId(), "视频已下架，不发送");
//                    return false;
//                }
//            }
//        }
        Long queryLiveId = null;
        queryLiveId = setting.getLiveId();
        if(null == queryLiveId){
            for (QwSopCourseFinishTempSetting.Setting a : setting.getSetting()) {
                if (StringUtils.isNotBlank(a.getLiveId())) {
                    queryLiveId = Long.valueOf(a.getLiveId());
                    break;
                }
            }
        }
        LiveWatchLog liveWatchLog = liveWatchLogMapper.selectOneLogByLiveIdAndQwUserIdAndExternalId(
                queryLiveId,
                String.valueOf(qwUser.getId()),
                qwSopLogs.getExternalId()
        );
        Integer courseType = setting.getCourseType();
        String logId = qwSopLogs.getId();
        if(null != liveWatchLog){
                    if (!QwSopLogsServiceImpl.isCourseTypeValid(courseType, liveWatchLog.getLogType())) {
                        // 作废消息
                        log.warn("SOP_LOG_ID:{}, 看课状态未满足，不发送", qwSopLogs.getId());
                        qwSopLogsService.updateQwSopLogsByWatchLogType(logId, "看课状态未满足，不发送");
                        return false;
                    }
        }
        else{
            log.warn("SOP_LOG_ID:{}, 无观看记录，不发送", qwSopLogs.getId());
            qwSopLogsService.updateQwSopLogsByWatchLogType(logId, "无观看记录，不发送");
            return false;
        }
//        if (qwSopLogs.getSendType() != 6 && noSop) {
//            // 客户的信息
////            QwExternalContactHParam contactHParam = new QwExternalContactHParam();
////            contactHParam.setUserId(qwUser.getQwUserId().trim());
////            contactHParam.setExternalUserId(qwSopLogs.getExternalUserId().trim());
////            contactHParam.setCorpId(qwUser.getCorpId().trim());
//            Integer courseType = setting.getCourseType();
//            if (setting.getType() == 2 && courseType != 0) {// 课程消息，进行复杂的条件判断
////                log.debug("企微查询：{}", contactHParam);
////                Long qwExternalContactId = qwExternalContactMapper.getQwExternalContactId(contactHParam);
//                FsCourseWatchLog watchLog = watchLogService.getWatchCourseLogVideoBySop(
//                        setting.getVideoId().longValue(),
//                        String.valueOf(qwUser.getId()),
//                        qwSopLogs.getExternalId()
//                );
//                log.debug("ID:{}-看课记录参数：videoID:{}， qwUserID:{}， extID:{}", qwSopLogs.getId(), setting.getVideoId().longValue(), qwUser.getId(), qwSopLogs.getExternalId());
//                log.debug("ID:{}-看课记录：{}", qwSopLogs.getId(), watchLog);
//                String logId = qwSopLogs.getId();
//                if (watchLog != null) {
//                    //新逻辑
//                    if (!QwSopLogsServiceImpl.isCourseTypeValid(courseType, watchLog.getLogType())) {
//                        // 作废消息
//                        log.warn("SOP_LOG_ID:{}, 看课状态未满足，不发送", qwSopLogs.getId());
//                        qwSopLogsService.updateQwSopLogsByWatchLogType(logId, "看课状态未满足，不发送");
//                        return false;
//                    }
//                } else {
//                    log.warn("SOP_LOG_ID:{}, 无观看记录，不发送", qwSopLogs.getId());
//                    qwSopLogsService.updateQwSopLogsByWatchLogType(logId, "无观看记录，不发送");
//                    return false;
//                }
//            }
//        }
        return true;
    }

    public void send(QwSopCourseFinishTempSetting.Setting content, QwUser qwUser, QwSopLogs qwSopLogs, Map<String, FsCoursePlaySourceConfig> miniMap, BaseVo parentVo) {
        BaseVo vo = new BaseVo();
        vo.setId(Long.parseLong(qwSopLogs.getId()));
        vo.setRoom(qwSopLogs.getSendType() == 6);
        vo.setUuid(qwUser.getUid());
        vo.setExId(qwSopLogs.getExternalUserId());
        vo.setServerId(qwUser.getServerId());
        vo.setCorpCode(parentVo.getCorpCode());
        vo.setCorpId(parentVo.getCorpId());
        vo.setQwUserId(qwUser.getId());
        try {
            content.setSendStatus(1);
            switch (content.getContentType()) {
                case "1":
                    // 文本
                    sendTxt(vo, content);
                    break;
                case "2":
                    // 图片
                    sendImg(vo, content);
                    break;
                case "3":
                    // 链接
                    sendLink(vo, content);
                    break;
                case "4":
                case "10":
                    sendMiniProgram(vo, content, miniMap, qwUser.getCompanyId());
                    break;
                case "5":
                    // 文件
                    sendFile(vo, content);
                    break;
                case "6":
                    // 视频
                    sendVideo(vo, content);
                    break;
                case "7":
                    // 语音
                    sendVoice(vo, content);
                    break;
                case "8":
                    // 视频号
                    sendWxVideo(vo, content);
                    break;
                case "99":
                    // 群发
                    sendTxtAtMsg(vo);
                    break;
                default:
                    // 未知类型，记录警告
                    log.error("SOP_LOG_ID:{}错误的发送类型: {}", qwSopLogs.getId(), content.getContentType());
                    break;
            }
        } catch (Exception e) {
            log.error("ID:{}-发送失败QW_SOP_ID：{},content:{},vo:{}", qwSopLogs.getId(), qwSopLogs.getId(), JSON.toJSONString(content), JSON.toJSONString(vo), e);
            content.setSendStatus(2);
            content.setSendRemarks("发送失败：" + e.getMessage());
        }
    }

    public void loginOut(QwUser user) {
        ipadSendUtils.loginOut(user.getUid(), user.getServerId());
    }
}
