package com.fs.app.service;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
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.company.domain.Company;
import com.fs.company.domain.CompanyMiniapp;
import com.fs.company.mapper.CompanyMapper;
import com.fs.company.service.ICompanyMiniappService;
import com.fs.course.config.CourseConfig;
import com.fs.course.domain.FsCoursePlaySourceConfig;
import com.fs.course.domain.FsCourseWatchLog;
import com.fs.course.service.IFsCourseWatchLogService;
import com.fs.his.domain.FsSignArticle;
import com.fs.his.domain.FsUser;
import com.fs.his.mapper.FsUserMapper;
import com.fs.his.service.IFsSignArticleService;
import com.fs.ipad.IpadSendUtils;
import com.fs.ipad.vo.*;
import com.fs.qw.domain.BindPhoneRedPacketRecord;
import com.fs.qw.domain.QwUser;
import com.fs.qw.domain.QwUserVideo;
import com.fs.qw.domain.RedPacket;
import com.fs.qw.mapper.BindPhoneRedPacketRecordMapper;
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.service.IRedPacketService;
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.system.service.ISysConfigService;
import com.fs.wxwork.dto.*;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
@Service
@AllArgsConstructor
public class IpadSendServer {
    private static final Pattern LINK_PATTERN = Pattern.compile("link=([^&]+)");
    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;

    @Autowired
    private ISysConfigService configService;

    @Autowired
    private IRedPacketService redPacketService;

    @Autowired
    private BindPhoneRedPacketRecordMapper bindPhoneRedPacketRecordMapper;

    @Autowired
    private CompanyMapper companyMapper;

    @Autowired
    private FsUserMapper fsUserMapper;

    @Autowired
    private IFsSignArticleService signArticleService;

    //private final LiveWatchLogMapper liveWatchLogMapper;


    /**
     * 直播间判定消息
     * @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;
//        }
        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;
    }

    private void sendMiniProgram(BaseVo vo, QwSopCourseFinishTempSetting.Setting content, Map<String, FsCoursePlaySourceConfig> miniMap, Long companyId) {
        String appid = content.getMiniprogramAppid();
        if(companyId != null && content.getMiniType() != null){
            List<CompanyMiniapp> list = companyMiniappService.list(new QueryWrapper<CompanyMiniapp>().eq("company_id", companyId).eq("type", content.getMiniType()));
            if(!list.isEmpty() && list.get(0) != null && StringUtils.isNotEmpty(list.get(0).getAppId())){
                appid = list.get(0).getAppId();
            }
        }
        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())
                .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 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 (qwSopLogs.getSendType() != 12 && 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()),
                        qwExternalContactId
                );
                log.debug("ID:{}-看课记录参数：videoID:{}， qwUserID:{}， extID:{}", qwSopLogs.getId(), setting.getVideoId().longValue(), qwUser.getId(), qwExternalContactId);
                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() == 12);
        vo.setUuid(qwUser.getUid());
        vo.setExId(qwSopLogs.getExternalUserId());
        vo.setServerId(qwUser.getServerId());
        vo.setCorpCode(parentVo.getCorpCode());
        vo.setCorpId(parentVo.getCorpId());
        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 "14":
                    log.info("===============进入授权手机号红包=============");
                    // 记录授权手机号红包发送记录
                    RedPacket redPacket = redPacketService.selectRedPacketById(content.getRedPacketId());
                    if (ObjectUtil.isNotEmpty(redPacket) && redPacket.getStatus().equals("0")) {
                        qwSopLogsService.updateQwSopLogsByWatchLogType(qwSopLogs.getId(),"手机号授权红包已禁用");
                    } else if (ObjectUtil.isNotEmpty(qwSopLogs.getFsUserId())) {
                        //查询用户领取记录
                        BindPhoneRedPacketRecord record = new BindPhoneRedPacketRecord();
                        record.setUserId(qwSopLogs.getFsUserId());
                        record.setCollectType("1");
                        List<BindPhoneRedPacketRecord> records = bindPhoneRedPacketRecordMapper.selectBindPhoneRedPacketRecordList(record);
                        if (ObjectUtil.isNotEmpty(records)) {
                            qwSopLogsService.updateQwSopLogsByWatchLogType(qwSopLogs.getId(),"用户已领取过手机号授权红包");
                        }
                    }
                    try{
                        Long businessId = addRedPacketCollectRecord(redPacket,qwUser, content,qwSopLogs);
                        content.setMiniprogramPage(quickProcess(content.getMiniprogramPage(),businessId));
                        //手机号授权红包
                        sendMiniProgram(vo, content, miniMap,qwUser.getCompanyId());
                    }catch (Exception e){
                        qwSopLogsService.updateQwSopLogsByWatchLogType(qwSopLogs.getId(), "手机号授权红包发放失败,请重新发送!");
                    }
                    break;
                case "15":
                    log.info("===============进入打卡文章=============");
                    FsSignArticle signArticle = signArticleService.selectFsSignArticleById(content.getSignArticleId());
                    if (signArticle == null) {
                        qwSopLogsService.updateQwSopLogsByWatchLogType(qwSopLogs.getId(),"打卡文章不存在");
                    }
                    try{
                        content.setMiniprogramPage(quickProcess(content.getMiniprogramPage(),content.getSignArticleId()));
                        //发送小程序
                        sendMiniProgram(vo, content, miniMap,qwUser.getCompanyId());
                    }catch (Exception e){
                        qwSopLogsService.updateQwSopLogsByWatchLogType(qwSopLogs.getId(), "打卡文章发放失败,请重新发送!");
                    }
                    break;
                case "21":
                    content.setSendStatus(0);
                    content.setSendRemarks("短信待发送");
                    break;
                default:
                    // 未知类型，记录警告
                    log.error("SOP_LOG_ID:{}错误的发送类型: {}", qwSopLogs.getId(), content.getContentType());
                    break;
            }
        } catch (Exception e) {
            log.error("ID:" + qwSopLogs.getId() + "-发送失败QW_SOP_ID：" + qwSopLogs.getId(), e);
            content.setSendStatus(2);
            content.setSendRemarks("发送失败：" + e.getMessage());
        }
    }

    public Long addRedPacketCollectRecord(RedPacket redPacket, QwUser qwUser, QwSopCourseFinishTempSetting.Setting content, QwSopLogs qwSopLogs) {

        try{
            String json = configService.selectConfigByKey("course.config");
            CourseConfig config = JSON.parseObject(json, CourseConfig.class);
            Date updateTime = createUpdateTime(content, new Date(), config);
            String companyUserId = String.valueOf(qwUser.getCompanyUserId()).trim();
            String companyId = String.valueOf(qwUser.getCompanyId()).trim();
            Long businessId = addRedPacketCollectRecord(qwUser,redPacket,content,qwSopLogs,updateTime,companyUserId,companyId,content.getChatId());
            return businessId;
        }catch (Exception e){
            log.error("授权手机号红包创建失败：qwUser={}，qwSopLogs={}",qwUser,qwSopLogs);
            return null;
        }
    }

    /**
     * 优化版快速处理方法
     */
    public static String quickProcess(String miniprogramPage, Long businessId) {
        if (miniprogramPage == null || businessId == null) {
            return miniprogramPage;
        }

        try {
            Matcher matcher = LINK_PATTERN.matcher(miniprogramPage);
            if (matcher.find()) {
                String encodedLink = matcher.group(1);

                // 第一次URL解码
                String decodedLink = java.net.URLDecoder.decode(encodedLink, "UTF-8");

                // 处理多次转义的情况：如果解码后仍有转义字符，继续解码
                String jsonStr = decodedLink;
                while (jsonStr.contains("\\\"") || jsonStr.contains("\\\\")) {
                    // 检查是否是合法的JSON格式
                    if (jsonStr.trim().startsWith("{") && jsonStr.trim().endsWith("}")) {
                        break; // 已经是JSON对象字符串，不需要再解码
                    }
                    // 尝试再次解码
                    try {
                        jsonStr = java.net.URLDecoder.decode(jsonStr, "UTF-8");
                    } catch (Exception e) {
                        // 如果解码失败，说明不是URL编码，跳出循环
                        break;
                    }
                }

                // 清理JSON字符串中的转义字符
                jsonStr = cleanJsonString(jsonStr);

                // 解析JSON
                JSONObject linkJson = JSON.parseObject(jsonStr);

                // 检查并添加businessId
                if (!linkJson.containsKey("businessId") ||
                        linkJson.getString("businessId") == null ||
                        linkJson.getString("businessId").isEmpty()) {

                    linkJson.put("businessId", businessId);

                    // 重新编码（只编码一次）
                    String updatedJson = linkJson.toJSONString();
                    String updatedEncoded = java.net.URLEncoder.encode(updatedJson, "UTF-8");

                    // 替换原link参数
                    return miniprogramPage.replace(
                            "link=" + encodedLink,
                            "link=" + updatedEncoded
                    );
                }
            }
            return miniprogramPage;
        } catch (Exception e) {
            // 记录错误日志，这里可以替换为你的日志框架
            System.err.println("处理小程序页面链接失败: " + e.getMessage());
            e.printStackTrace();
            // 根据业务需求，可以选择抛出异常或返回原字符串
            // throw new RuntimeException("处理小程序页面链接失败", e);
            return miniprogramPage; // 失败时返回原字符串，避免影响主流程
        }
    }

    /**
     * 清理JSON字符串中的多余转义
     */
    private static String cleanJsonString(String jsonStr) {
        if (jsonStr == null || jsonStr.isEmpty()) {
            return jsonStr;
        }

        String result = jsonStr;

        // 移除多余的转义
        result = result.replace("\\\"", "\"");
        result = result.replace("\\\\", "\\");

        // 处理开头和结尾的转义引号
        if (result.startsWith("\"") && result.endsWith("\"")) {
            result = result.substring(1, result.length() - 1);
        }

        return result;
    }

    /**
     * 过期时间
     *
     * @param setting
     * @param sendTime
     * @param config
     * @return
     */
    private Date createUpdateTime(QwSopCourseFinishTempSetting.Setting setting, Date sendTime, CourseConfig config) {

        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());

        return updateTime;
    }

    /**
     * 增加授权手机号红包发放记录、领取记录
     *
     * @param companyId
     * @param qwUser
     * @param redPacket
     * @param content
     * @param qwSopLogs
     * @param sendTime
     * @param companyUserId
     * @param chatId
     */
    private Long addRedPacketCollectRecord(QwUser qwUser, RedPacket redPacket, QwSopCourseFinishTempSetting.Setting content,
                                          QwSopLogs qwSopLogs,
                                          Date sendTime,
                                          String companyUserId,
                                          String companyId,
                                          String chatId) {
        try {
            // 参数校验
            if (content == null || qwSopLogs == null || sendTime == null) {
                log.error("添加授权手机号红包记录失败：必要参数为空 [content:{}, qwSopLogs:{}, sendTime:{}]",
                        content, qwSopLogs, sendTime);
                return null;
            }

            // 验证授权手机号红包ID
            if (content.getRedPacketId() == null) {
                log.error("授权手机号红包ID为空");
                return null;
            }

            // 查询授权手机号红包信息
            if (redPacket == null) {
                log.error("未找到对应的授权手机号红包信息 [luckyBagId:{}]", content.getRedPacketId());
                return null;
            }

            // 检查授权手机号红包状态
            if (redPacket.getStatus().equals("0")) {
                log.error("授权手机号红包被禁用 [luckyBagId:{}]", content.getRedPacketId());
                return null;
            }

            // 查询公司信息
            Company company = (Company)redisCache.getCacheObject("redPacketCompanyId:"+companyId);
            if (company == null) {
                company = companyMapper.selectCompanyById(Long.valueOf(companyId));
                redisCache.setCacheObject("redPacketCompanyId:"+companyId, company, 1 , TimeUnit.DAYS);
                log.error("未找到对应的公司信息 [companyId:{}]", companyId);
            }

            // 构建授权手机号红包记录
            BindPhoneRedPacketRecord bindPhoneRedPacketRecord = buildRePacketRecord(qwUser, content, qwSopLogs, sendTime,
                    companyUserId, companyId, chatId, company, redPacket);
            bindPhoneRedPacketRecord.setSendTime(new Date());
            bindPhoneRedPacketRecord.setCollectType("0");
            // 插入记录并返回ID
            int result = bindPhoneRedPacketRecordMapper.insertBindPhoneRedPacketRecord(bindPhoneRedPacketRecord);
            if (result <= 0) {
                log.error("授权手机号红包记录插入失败 [luckyBagId:{}]", content.getRedPacketId());
                return null;
            }

            // 返回新增记录的ID
            Long recordId = bindPhoneRedPacketRecord.getId();
            if (recordId == null) {
                log.error("授权手机号红包记录插入成功但未返回ID [luckyBagId:{}]", content.getRedPacketId());
                return null;
            }

            log.info("授权手机号红包记录添加成功 [recordId:{}, luckyBagId:{}]", recordId, content.getRedPacketId());
            return recordId;

        } catch (NumberFormatException e) {
            log.error("ID转换失败 [companyId:{}, companyUserId:{}]", companyId, companyUserId, e);
            return null;
        } catch (Exception e) {
            log.error("ID:" + (content != null ? content.getRedPacketId() : "unknown") + "-添加授权手机号红包记录失败", e);
            return null;
        }
    }

    /**
     * 构建授权手机号红包记录对象
     */
    private BindPhoneRedPacketRecord buildRePacketRecord(QwUser qwUser,QwSopCourseFinishTempSetting.Setting content,
                                                      QwSopLogs qwSopLogs,
                                                      Date sendTime,
                                                      String companyUserId,
                                                      String companyId,
                                                      String chatId,
                                                      Company company,
                                                      RedPacket redPacket) {
        BindPhoneRedPacketRecord record = new BindPhoneRedPacketRecord();
        record.setQwUserId(qwUser.getQwUserId());
        record.setQwUserName(qwUser.getQwUserName());
        record.setRedPacketId(content.getRedPacketId());
        record.setCollectType("3");
        record.setCompanyId(Long.valueOf(companyId));
        record.setUserId(qwSopLogs.getFsUserId());
        if (ObjectUtil.isNotEmpty(qwSopLogs.getFsUserId())){
            FsUser fsUser = fsUserMapper.selectFsUserByUserId(qwSopLogs.getFsUserId());
            record.setUserName(ObjectUtil.isNotEmpty(fsUser)?fsUser.getNickName():null);
        }
        record.setCompanyName(company.getCompanyName());
        record.setCompanyUserId(Long.valueOf(companyUserId));
        record.setSendLink(content.getMiniprogramPage());

        // 设置奖励类型和聊天信息
        if (StringUtils.isNotEmpty(chatId)) {
            record.setRewardType(1L);
            record.setChatId(chatId);
            record.setExternalUserName(qwSopLogs.getExternalUserName());
        } else {
            record.setRewardType(2L);
        }

        record.setAmount(redPacket.getAmount());

        return record;
    }

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