package com.fs.app.service;

import com.alibaba.fastjson.JSON;
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.CompanyMiniapp;
import com.fs.company.service.ICompanyMiniappService;
import com.fs.course.domain.FsCoursePlaySourceConfig;
import com.fs.course.domain.FsCourseWatchLog;
import com.fs.course.service.IFsCourseWatchLogService;
import com.fs.ipad.IpadSendUtils;
import com.fs.ipad.vo.*;
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.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

@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 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() != 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());
        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;
                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());
    }
}
