package com.qmth.distributed.print.business.service.impl;

import com.alibaba.fastjson.JSON;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qmth.distributed.print.business.entity.BasicMessage;
import com.qmth.distributed.print.business.entity.ExamTask;
import com.qmth.distributed.print.business.enums.MessageEnum;
import com.qmth.distributed.print.business.mapper.BasicMessageMapper;
import com.qmth.distributed.print.business.service.BasicMessageService;
import com.qmth.distributed.print.business.service.ExamTaskService;
import com.qmth.distributed.print.business.util.SmsUtils;
import com.qmth.teachcloud.common.bean.params.ApproveUserResult;
import com.qmth.teachcloud.common.contant.SpringContextHolder;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.SysConfig;
import com.qmth.teachcloud.common.entity.SysUser;
import com.qmth.teachcloud.common.enums.EnumResult;
import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
import com.qmth.teachcloud.common.service.CommonCacheService;
import com.qmth.teachcloud.common.service.SysConfigService;
import com.qmth.teachcloud.common.util.ServletUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 短信消息发送
 * @Author: CaoZixuan
 * @Date: 2021-04-28
 */
@Service
public class BasicMessageServiceImpl extends ServiceImpl<BasicMessageMapper, BasicMessage> implements BasicMessageService {
    @Resource
    private SysConfigService sysConfigService;

    @Resource
    private CommonCacheService commonCacheService;

    @Autowired
    private SmsUtils smsUtils;

    @Override
    public IPage<BasicMessage> listByMessageType(MessageEnum messageType, Boolean sendStatus, String mobileNumber, Integer pageNumber, Integer pageSize) {
        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
        Page<BasicMessage> page = new Page<>(pageNumber, pageSize);
        QueryWrapper<BasicMessage> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(BasicMessage::getSchoolId, schoolId);
        if (!Objects.isNull(messageType)) {
            queryWrapper.lambda().eq(BasicMessage::getMessageType, messageType);
        }
        if (Objects.nonNull(sendStatus)) {
            if (sendStatus) {
                queryWrapper.lambda().eq(BasicMessage::getSendStatus, "OK");
            } else {
                queryWrapper.lambda().ne(BasicMessage::getSendStatus, "OK");
            }
        }
        if (StringUtils.isNotBlank(mobileNumber)) {
            queryWrapper.lambda().like(BasicMessage::getMobileNumber, "%" + mobileNumber + "%");
        }
        queryWrapper.lambda().orderByDesc(BasicMessage::getCreateTime);
        return this.page(page, queryWrapper);
    }

    @Override
    public List<EnumResult> listMessageTypes() {
        return MessageEnum.listTypes();
    }

    @Override
    public void resendSmsTaskById(Long id) {
        BasicMessage basicMessage = this.getById(id);
        if (Objects.isNull(basicMessage)) {
            return;
        }
        this.saveMessageResendLog(basicMessage);
    }

    /**
     * 发送短信
     *
     * @param userId
     * @param userName
     * @param mobileNumber
     * @param paperNumber
     * @param courseCode
     * @param variableParams
     * @param messageType
     * @param createId
     * @param remark
     */
    public void saveMessageSendLog(Long schoolId, Long userId, String userName, String mobileNumber, String paperNumber, String courseCode, String variableParams, MessageEnum messageType, Long createId, String remark) {
        BasicMessage basicMessage = new BasicMessage();
        String templateCode = null;
        try {
            // code和content
            Map<String, String> enumInfo = smsUtils.getCodeAndContentByEnum(messageType);
            if (!enumInfo.containsKey("templateCode")) {
                throw ExceptionResultEnum.ERROR.exception("未找到短信模板Code");
            }
            templateCode = enumInfo.get("templateCode");
            if (StringUtils.isBlank(templateCode)) {
                throw ExceptionResultEnum.ERROR.exception("阿里云短信模板Code必填");
            }

            // 发送短信参数配置验证
            SysConfig sysConfig = sysConfigService.getByKey("sys.message.enable");
            if (sysConfig == null) {
                throw ExceptionResultEnum.ERROR.exception("未找到发送短信开关配置参数，默认不发送");
            }
            if (sysConfig.getConfigValue() == null) {
                throw ExceptionResultEnum.ERROR.exception("未正确配置发送短信开关参数，默认不发送");
            }
            if (sysConfig.getConfigValue().equals("false")) {
                throw ExceptionResultEnum.ERROR.exception("发送短信开关设置为已关闭");
            }

            // 参数校验
            if (StringUtils.isBlank(userName)) {
                throw ExceptionResultEnum.ERROR.exception("用户名称必填");
            }
            if (StringUtils.isBlank(mobileNumber)) {
                throw ExceptionResultEnum.ERROR.exception("用户手机号必填");
            }
            if (StringUtils.isBlank(variableParams)) {
                throw ExceptionResultEnum.ERROR.exception("短信内容参数值必填");
            }

            // 调用阿里云短信平台发送短信
            SendSmsResponse sendSmsResponse = smsUtils.sendSms(mobileNumber, templateCode, variableParams);
            if (sendSmsResponse == null) {
                throw ExceptionResultEnum.ERROR.exception("阿里云短信发送接口调用失败");
            }
            basicMessage.setSendStatus(sendSmsResponse.getCode());
            basicMessage.setSendResult(sendSmsResponse.getMessage());

        } catch (Exception e) {
            basicMessage.setSendStatus("SYSTEM_ERROR");
            basicMessage.setSendResult(e.getMessage());
        } finally {
            basicMessage.setId(SystemConstant.getDbUuid());
            basicMessage.setSchoolId(schoolId);
            basicMessage.setUserId(userId);
            basicMessage.setUserName(userName);
            basicMessage.setMobileNumber(mobileNumber);
            basicMessage.setPaperNumber(paperNumber);
            basicMessage.setCourseCode(courseCode);
            basicMessage.setTemplateCode(templateCode);
            basicMessage.setVariableParams(variableParams);
            basicMessage.setMessageType(messageType);
            basicMessage.setBusinessOperate(messageType.getName());
            basicMessage.setRemark(remark);
            basicMessage.setResendCount(0);
            basicMessage.setCreateId(createId);
            basicMessage.setCreateTime(System.currentTimeMillis());
            this.save(basicMessage);
        }
    }

    /**
     * 失败重发
     *
     * @param basicMessage
     */
    public void saveMessageResendLog(BasicMessage basicMessage) {
        try {
            if (basicMessage == null) {
                return;
            }
            if ("OK".equals(basicMessage.getSendStatus())) {
                return;
            }

            if (!StringUtils.isBlank(basicMessage.getMobileNumber())) {
                // 调用阿里云短信平台发送短信
                SendSmsResponse sendSmsResponse = smsUtils.sendSms(basicMessage.getMobileNumber(), basicMessage.getTemplateCode(), basicMessage.getVariableParams());
                if (sendSmsResponse == null) {
                    throw ExceptionResultEnum.ERROR.exception("阿里云短信发送接口调用失败");
                }
                basicMessage.setSendStatus(sendSmsResponse.getCode());
                basicMessage.setSendResult(sendSmsResponse.getMessage());
            }
        } catch (Exception e) {
            basicMessage.setSendStatus("SYSTEM_ERROR");
            basicMessage.setSendResult(e.getMessage());
        } finally {
            // 重试次数+1
            basicMessage.setResendCount(basicMessage.getResendCount() + 1);
            this.updateById(basicMessage);
        }
    }


    @Override
    public void noticeOfExamTaskAudit(List<Long> examTaskIdList, MessageEnum messageType, SysUser sysUser) {
        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
        ExamTaskService examTaskService = SpringContextHolder.getBean(ExamTaskService.class);
        for (Long examTaskId : examTaskIdList) {
            ExamTask examTask = examTaskService.getById(examTaskId);
            if (Objects.nonNull(examTask)) {
                String courseCode = examTask.getCourseCode();
                String courseName = examTask.getCourseName();
                String paperNumber = examTask.getPaperNumber();
                // 获取短信接收对象的信息
                Long userId = examTask.getUserId();
                SysUser user = commonCacheService.userCache(userId);
                if (Objects.nonNull(user)) {
                    String userName = user.getRealName();
                    String mobileNumber = user.getMobileNumber();

                    Map<String, String> jsonMap = new HashMap<>();
                    jsonMap.put("userName", userName);
                    jsonMap.put("courseName", courseName);
                    jsonMap.put("paperNumber", paperNumber);
                    String variableParams = JSON.toJSONString(jsonMap);
                    String remark = String.format("命题任务ID：%s", examTaskId);
                    this.saveMessageSendLog(schoolId, userId, userName, mobileNumber, paperNumber, courseCode, variableParams, messageType, sysUser.getId(), remark);
                } else {
                    String remark = String.format("命题任务ID：%s，用户不存在", examTaskId);
                    this.saveMessageSendLog(schoolId, userId, null, null, paperNumber, courseCode, null, messageType, sysUser.getId(), remark);
                }
            }
        }

    }

    /**
     * 发送给命题老师-待办提醒
     *
     * @param examTasks
     */
    @Override
    public void sendNoticeTaskCreate(ExamTask... examTasks) {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
        // 指派命题老师的命题任务
        Map<Long, List<String>> collects = Arrays.stream(examTasks).filter(m -> m.getUserId() != null).collect(Collectors.groupingBy(ExamTask::getUserId, Collectors.mapping(m -> String.valueOf(m.getId()), Collectors.toList())));
        for (Map.Entry<Long, List<String>> longListEntry : collects.entrySet()) {
            Long userId = longListEntry.getKey();
            List<String> ids = longListEntry.getValue();
            SysUser user = commonCacheService.userCache(userId);
            if (Objects.nonNull(user)) {
                String userName = user.getRealName();
                String mobileNumber = user.getMobileNumber();

                Map<String, Object> jsonMap = new HashMap<>();
                jsonMap.put("userName", userName);
                jsonMap.put("count", ids.size());
                String variableParams = JSON.toJSONString(jsonMap);
                String remark = String.format("命题任务ID：%s", String.join(",", ids));
                this.saveMessageSendLog(schoolId, userId, userName, mobileNumber, null, null, variableParams, MessageEnum.NOTICE_OF_EXAM_TASK_CREATED, sysUser.getId(), remark);
            } else {
                String remark = String.format("命题任务ID：%s，用户不存在", String.join(",", ids));
                this.saveMessageSendLog(schoolId, userId, null, null, null, null, null, MessageEnum.NOTICE_OF_EXAM_TASK_CREATED, sysUser.getId(), remark);
            }
        }
    }

    @Override
    public void sendNoticeTaskAuditCreateOrReview(ExamTask examTask, MessageEnum messageType) {
        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        // 考务老师(命题任务创建人)
        Long userId = examTask.getCreateId();
        SysUser user = commonCacheService.userCache(userId);
        if (Objects.nonNull(user)) {
            String userName = user.getRealName();
            String mobileNumber = user.getMobileNumber();
            String paperNumber = examTask.getPaperNumber();
            String courseCode = examTask.getCourseCode();
            String courseName = examTask.getCourseName();

            Map<String, Object> jsonMap = new HashMap<>();
            jsonMap.put("userName", userName);
            StringJoiner sj = new StringJoiner("、").add(courseName).add(paperNumber);
            jsonMap.put("courseName", sj.toString());
            String variableParams = JSON.toJSONString(jsonMap);
            String remark = String.format("命题任务ID：%s", examTask.getId().toString());
            this.saveMessageSendLog(schoolId, userId, userName, mobileNumber, paperNumber, courseCode, variableParams, messageType, sysUser.getId(), remark);
        } else {
            String remark = String.format("命题任务ID：%s，用户不存在", examTask.getId().toString());
            this.saveMessageSendLog(schoolId, userId, null, null, null, null, null, messageType, sysUser.getId(), remark);
        }
    }

    @Override
    public void sendNoticeExpireOrOverdue(MessageEnum messageType, Long userId, List<String> ids) {
        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
        // 考务老师(命题任务创建人)
        SysUser user = commonCacheService.userCache(userId);
        if (Objects.nonNull(user)) {
            String userName = user.getRealName();
            String mobileNumber = user.getMobileNumber();
            Map<String, Object> jsonMap = new HashMap<>();
            jsonMap.put("userName", userName);
            jsonMap.put("count", ids.size());
            String variableParams = JSON.toJSONString(jsonMap);
            String remark = String.format("命题任务ID：%s", String.join(",", ids));
            this.saveMessageSendLog(schoolId, userId, userName, mobileNumber, null, null, variableParams, messageType, null, remark);
        } else {
            String remark = String.format("命题任务ID：%s，用户不存在", String.join(",", ids));
            this.saveMessageSendLog(schoolId, userId, null, null, null, null, null, messageType, null, remark);
        }
    }

    @Override
    public void resendSmsTask() {
        SysConfig sysConfig = sysConfigService.getByKey("sys.message.resendCount");
        if (sysConfig != null) {
            Integer resendCount = StringUtils.isBlank(sysConfig.getConfigValue()) ? 0 : Integer.valueOf(sysConfig.getConfigValue());
            QueryWrapper<BasicMessage> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().ne(BasicMessage::getSendStatus, "OK").lt(BasicMessage::getResendCount, resendCount);
            List<BasicMessage> basicMessageList = this.list(queryWrapper);
            if (basicMessageList != null && basicMessageList.size() > 0) {
                for (BasicMessage basicMessage : basicMessageList) {
                    this.saveMessageResendLog(basicMessage);
                }
            }
        }
    }

    @Override
    public void sendNoticeTaskAuditFlow(ExamTask examTask, List<ApproveUserResult> users, MessageEnum messageType) {
        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        // 考务老师(命题任务创建人)
        for (ApproveUserResult user : users) {
            String userName = user.getRealName();
            String mobileNumber = user.getMobileNumber();
            String paperNumber = examTask.getPaperNumber();
            String courseCode = examTask.getCourseCode();
            String courseName = examTask.getCourseName();
            Map<String, Object> jsonMap = new HashMap<>();
            jsonMap.put("userName", userName);
            StringJoiner sj = new StringJoiner("、").add(courseName).add(paperNumber);
            jsonMap.put("courseName", sj.toString());
            String variableParams = JSON.toJSONString(jsonMap);
            String remark = String.format("命题任务ID：%s", examTask.getId().toString());
            this.saveMessageSendLog(schoolId, user.getId(), userName, mobileNumber, paperNumber, courseCode, variableParams, messageType, sysUser.getId(), remark);
        }
    }

    /**
     * 发送审核抄送短信
     *
     * @param examTask
     * @param users
     * @param auditUserNames
     * @param messageType
     */
    @Override
    public void sendNoticeAuditCopyUser(ExamTask examTask, List<ApproveUserResult> users, String auditUserNames, MessageEnum messageType) {
        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        for (ApproveUserResult user : users) {
            String userName = user.getRealName();
            String mobileNumber = user.getMobileNumber();
            String paperNumber = examTask.getPaperNumber();
            String courseCode = examTask.getCourseCode();
            String courseName = examTask.getCourseName();
            Map<String, Object> jsonMap = new HashMap<>();
            jsonMap.put("userName", userName);
            StringJoiner sj = new StringJoiner("、").add(courseName).add(paperNumber);
            jsonMap.put("courseName", sj.toString());
            jsonMap.put("auditUserNames", auditUserNames);
            String variableParams = JSON.toJSONString(jsonMap);
            String remark = String.format("命题任务ID：%s", examTask.getId().toString());
            this.saveMessageSendLog(schoolId, user.getId(), userName, mobileNumber, paperNumber, courseCode, variableParams, messageType, sysUser.getId(), remark);
        }
    }

    @Override
    public void sendNoticeUploadStructure(String paperNumber, String courseCode, String courseName, Long userId, MessageEnum messageType, SysUser sysUser) {
        QueryWrapper<BasicMessage> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(BasicMessage::getPaperNumber, paperNumber).eq(BasicMessage::getCourseCode, courseCode).eq(BasicMessage::getUserId, userId).eq(BasicMessage::getMessageType, messageType);
        List<BasicMessage> list = this.list(queryWrapper);
        if (!CollectionUtils.isEmpty(list)) {
            return;
        }
        SysUser user = commonCacheService.userCache(userId);
        if (Objects.nonNull(user)) {
            String userName = user.getRealName();
            String mobileNumber = user.getMobileNumber();

            Map<String, Object> jsonMap = new HashMap<>();
            jsonMap.put("userName", userName);
            StringJoiner sj = new StringJoiner("、").add(courseName).add(paperNumber);
            jsonMap.put("courseName", sj.toString());
            String variableParams = JSON.toJSONString(jsonMap);
            this.saveMessageSendLog(sysUser.getSchoolId(), userId, userName, mobileNumber, paperNumber, courseCode, variableParams, messageType, sysUser.getId(), null);
        }
    }
}
