package com.xinelu.quartz.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.aliyuncs.exceptions.ClientException;
import com.xinelu.common.config.AliYunSmsTwoConfig;
import com.xinelu.common.config.PushMessageRestrictions;
import com.xinelu.common.enums.*;
import com.xinelu.manage.domain.shortmessagesendrecord.ShortMessageSendRecord;
import com.xinelu.manage.domain.signpatientmanageroutenode.SignPatientManageRouteNode;
import com.xinelu.manage.domain.textmessage.SmsReport;
import com.xinelu.manage.domain.textmessage.TaskMessageBackEntity;
import com.xinelu.manage.dto.smssend.SmsInfoDTO;
import com.xinelu.manage.mapper.shortmessagesendrecord.ShortMessageSendRecordMapper;
import com.xinelu.manage.mapper.signpatientmanageroutenode.SignPatientManageRouteNodeMapper;
import com.xinelu.manage.service.patienttaskstatistics.IPatientTaskStatisticsService;
import com.xinelu.manage.vo.signpatientmanageroute.SignPatientManageRouteVO;
import com.xinelu.manage.vo.signpatientmanageroutenode.TextMessage;
import com.xinelu.manage.vo.subscribemessagesendrecord.RecordNum;
import com.xinelu.mobile.utils.SmsSendUtils;
import com.xinelu.quartz.service.SendTextMessageService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description 短信发送定时任务业务层
 * @Author zh
 * @Date 2024-07-22
 */
@Service
@Slf4j
public class SendTextMessageServiceImpl implements SendTextMessageService {

    @Resource
    private SignPatientManageRouteNodeMapper signPatientManageRouteNodeMapper;
    @Resource
    private SmsSendUtils smsSendUtils;
    @Resource
    private AliYunSmsTwoConfig aliYunSmsTwoConfig;
    @Resource
    private PushMessageRestrictions pushMessageRestrictions;
    @Resource
    private ShortMessageSendRecordMapper shortMessageSendRecordMapper;
    @Resource
    private IPatientTaskStatisticsService patientTaskStatisticsService;
    @Value("${aiob.callBackUrl}")
    private String callBackUrl;

    /**
     * 签约患者管理任务路径节点短信发送定时任务
     *
     * @throws ClientException 发送信息
     */
    @Override
    public void sendTextMessageSendTask() throws ClientException {
        //查询短信发送数据
        List<TextMessage> textMessages = signPatientManageRouteNodeMapper.selectMessagePushSign();
        if (CollectionUtils.isEmpty(textMessages)) {
            return;
        }
        //条件过滤后短信信息
        List<TextMessage> messages = new ArrayList<>();
        //超时短信ids
        List<Long> expiredManageRouteNodeIds = new ArrayList<>();
        LocalDateTime now = LocalDateTime.now();
        LocalDate nowDate = LocalDate.now();
        for (TextMessage textMessage : textMessages) {
            //判断推送状态
            if (Objects.isNull(textMessage.getMessagePushSign()) || textMessage.getMessagePushSign() != 1) {
                continue;
            }
            //过滤脏数据 if (StringUtils.isBlank(textMessage.getPatientType()) || Objects.isNull(textMessage.getRouteNodeDay()))
            if (StringUtils.isBlank(textMessage.getPatientType())) {
                continue;
            }
            //模版暂时处理
            if (StringUtils.isBlank(textMessage.getTextMessageId()) || !aliYunSmsTwoConfig.getTemplateCode().equals(textMessage.getTextMessageId())) {
                continue;
            }
            LocalDate localDate = null;
            //后续加入根据类型判断使用具体那个时间
            if (Objects.nonNull(textMessage.getDischargeTime()) && Objects.nonNull(textMessage.getRouteNodeDay())) {
                localDate = textMessage.getDischargeTime().plusDays(textMessage.getRouteNodeDay());
            }
            if (Objects.isNull(textMessage.getDischargeTime()) && Objects.nonNull(textMessage.getVisitDate()) && Objects.nonNull(textMessage.getRouteNodeDay())) {
                localDate = textMessage.getVisitDate().plusDays(textMessage.getRouteNodeDay());
            }
            //没有天数按执行时间处理NodePlanTime
            if (Objects.isNull(textMessage.getRouteNodeDay()) && Objects.nonNull(textMessage.getNodePlanTime())) {
                localDate = textMessage.getNodePlanTime().toLocalDate();//新加的外呼立即执行没有getRouteNodeDay
            }
            if (Objects.isNull(localDate)) {
                continue;
            }
            boolean before = localDate.isBefore(nowDate) || localDate.isEqual(nowDate);
            if (before) {
                //超出7天，更改状态
                long until = localDate.until(LocalDate.now(), ChronoUnit.DAYS);
                if (until >= pushMessageRestrictions.getTime()) {
                    expiredManageRouteNodeIds.add(textMessage.getSignPatientManageRouteNodeId());
                    continue;
                }
                //没有天数按执行时间处理NodePlanTime
                if (Objects.isNull(textMessage.getRouteNodeDay()) && now.isBefore(textMessage.getNodePlanTime())) {
                    continue;
                }
                textMessage.setRouteNodeName(RouteNodeNameEnum.getNameByInfo(textMessage.getRouteNodeName()).getName());
                messages.add(textMessage);
            }
        }
        //更改过期执行状态
        if (CollectionUtils.isNotEmpty(expiredManageRouteNodeIds)) {
            signPatientManageRouteNodeMapper.updateNodeExecuteStatusByIds(expiredManageRouteNodeIds, NodeExecuteStatusEnum.EXECUTED.getInfo(), null, NodeExecuteResultStatusEnum.EXPIRED.getInfo(), null, now);
        }

        //判断路径节点，组装数据
//            if (textMessage.getRouteNodeName().equals(RouteNodeNameEnum.AFTER_DISCHARGE.getInfo()) || textMessage.getRouteNodeName().equals(RouteNodeNameEnum.AFTER_VISIT_DISCHARGE.getInfo())) {
//                if (textMessage.getPatientType().equals(PatientTypeEnum.DISCHARGED_PATIENT.getInfo()) && Objects.nonNull(textMessage.getDischargeTime())) {
//                    LocalDate localDate = textMessage.getDischargeTime().plusDays(textMessage.getRouteNodeDay());
//                    boolean before = localDate.isBefore(LocalDate.now()) || localDate.isEqual(LocalDate.now());
//                    if (before) {
//                        textMessage.setRouteNodeName(RouteNodeNameEnum.AFTER_DISCHARGE.getName());
//                        messages.add(textMessage);
//                    }
//                }
//            }
//            if (textMessage.getRouteNodeName().equals(RouteNodeNameEnum.AFTER_ADMISSION.getInfo())) {
//                if (textMessage.getPatientType().equals(PatientTypeEnum.IN_HOSPITAL_PATIENT.getInfo()) && Objects.nonNull(textMessage.getAdmissionTime())) {
//                    LocalDate localDate = textMessage.getAdmissionTime().plusDays(textMessage.getRouteNodeDay());
//                    boolean before = localDate.isBefore(LocalDate.now()) || localDate.isEqual(LocalDate.now());
//                    if (before) {
//                        textMessage.setRouteNodeName(RouteNodeNameEnum.AFTER_ADMISSION.getName());
//                        messages.add(textMessage);
//                    }
//                }
//            }
//            if (textMessage.getRouteNodeName().equals(RouteNodeNameEnum.AFTER_CONSULTATION.getInfo()) || textMessage.getRouteNodeName().equals(RouteNodeNameEnum.AFTER_VISIT_DISCHARGE.getInfo())) {
//                if (textMessage.getPatientType().equals(PatientTypeEnum.OUTPATIENT.getInfo()) && textMessage.getAdmissionTime() == null && Objects.nonNull(textMessage.getVisitDate())) {
//                    LocalDate localDate = textMessage.getVisitDate().plusDays(textMessage.getRouteNodeDay());
//                    boolean before = localDate.isBefore(LocalDate.now()) || localDate.isEqual(LocalDate.now());
//                    if (before) {
//                        textMessage.setRouteNodeName(RouteNodeNameEnum.AFTER_CONSULTATION.getName());
//                        messages.add(textMessage);
//                    }
//                }
//            }
//        }
        //节点推送数量
        List<Long> collect = messages.stream().filter(Objects::nonNull).map(TextMessage::getSignPatientManageRouteNodeId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
        List<RecordNum> recordNums = shortMessageSendRecordMapper.selectShortMessageRecordCountByManageRouteNodeIds(collect);//后续是否加入通用状态
        //发送
        //发送失败ids
        List<Long> failSignPatientManageRouteNodeIds = new ArrayList<>();

        Set<Long> patientIdSet = new HashSet<>();
        if (CollectionUtils.isNotEmpty(messages)) {
            List<Long> ids = new ArrayList<>();
            for (TextMessage message : messages) {
                SmsInfoDTO smsInfoDTO = new SmsInfoDTO();
                smsInfoDTO.setPhoneNumbers(message.getPatientPhone());
                smsInfoDTO.setSignName(aliYunSmsTwoConfig.getSignName());
                // 根据模版id发送
                smsInfoDTO.setTemplateCode(message.getTextMessageId());
                Boolean aBoolean = smsSendUtils.sendTextMessage(smsInfoDTO);
                ShortMessageSendRecord shortMessageSendRecord = new ShortMessageSendRecord();
                shortMessageSendRecord.setMessageType(ShortMessageTypeEnum.COMMON.getInfo());
                shortMessageSendRecord.setPatientId(message.getPatientId());
                shortMessageSendRecord.setPatientPhone(message.getPatientPhone());
                shortMessageSendRecord.setManageRouteNodeId(message.getSignPatientManageRouteNodeId());
                shortMessageSendRecord.setSendTime(LocalDateTime.now());
                shortMessageSendRecord.setMessageTemplateId(message.getTextMessageId());
                shortMessageSendRecord.setMessageNodeContent(message.getMessageNodeContent());
                shortMessageSendRecord.setCreateTime(LocalDateTime.now());
                //成功
                if (aBoolean) {
                    ids.add(message.getSignPatientManageRouteNodeId());
                    shortMessageSendRecord.setErrorCode(0L);
                    shortMessageSendRecord.setErrorStatus(ErrorStatusEnum.success.getValue());

                } else {
                    //失败
                    shortMessageSendRecord.setErrorCode(1L);
                    shortMessageSendRecord.setErrorStatus(ErrorStatusEnum.fail.getValue());
                    RecordNum recordNum = recordNums.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getManageRouteNodeId()) && item.getManageRouteNodeId().equals(message.getSignPatientManageRouteNodeId())).findFirst().orElse(new RecordNum());
                    //三次失败
                    if (Objects.nonNull(recordNum.getNum()) && recordNum.getNum() >= pushMessageRestrictions.getNumber()) {
                        failSignPatientManageRouteNodeIds.add(message.getSignPatientManageRouteNodeId());
                    }
                }
                shortMessageSendRecordMapper.insertShortMessageSendRecord(shortMessageSendRecord);
                // 修改患者任务统计表
                patientIdSet.add(message.getPatientId());
            }
            //修改节点状态
            if (CollectionUtils.isNotEmpty(ids)) {
                signPatientManageRouteNodeMapper.updateNodeExecuteStatusByIds(ids, NodeExecuteStatusEnum.EXECUTED.getInfo(), null, NodeExecuteResultStatusEnum.SUCCESS.getInfo(), null, now);
            }
            //修改节点状态
            if (CollectionUtils.isNotEmpty(failSignPatientManageRouteNodeIds)) {
                signPatientManageRouteNodeMapper.updateNodeExecuteStatusByIds(failSignPatientManageRouteNodeIds, NodeExecuteStatusEnum.EXECUTED.getInfo(), null, NodeExecuteResultStatusEnum.FAILURE.getInfo(), null, now);
            }

            // 患者任务统计表修改
            if (CollectionUtils.isNotEmpty(patientIdSet)) {
                patientTaskStatisticsService.updateNum(new ArrayList<>(patientIdSet));
            }
        }
    }

    @Override
    public List<TaskMessageBackEntity> taskMessageBack(TaskMessageBackEntity taskMessageBackEntity) {
        // 接口获取外呼回调数据app
        List<TaskMessageBackEntity> taskMessageBackEntityList = new ArrayList<>();
        HttpEntity<JSONObject> requestEntity = new HttpEntity<>((JSONObject) JSON.toJSON(taskMessageBackEntity));
        RestTemplate restTemplate = new RestTemplate();
        log.info("接口获取短信回调数据");
        ResponseEntity<String> responseEntity = restTemplate.exchange(callBackUrl + "/getMessageBackList", HttpMethod.POST, requestEntity, String.class);
        JSONObject object = JSON.parseObject(responseEntity.getBody());
        if (object == null || object.getInteger("code") == null || object.getInteger("code") != 0) {
            return null;
        }
        if (object.containsKey("data")) {
            JSONArray data = object.getJSONArray("data");
            if (data != null && data.size() > 0) {
                taskMessageBackEntityList = data.toJavaList(TaskMessageBackEntity.class);
            }
        }
        log.info("共短信回调数据" + taskMessageBackEntityList.size() + "条");
        return taskMessageBackEntityList;
    }

    @Override
    public JSONObject taskTextMessageSendBack(SmsReport data, List<ShortMessageSendRecord> shortMessageSendRecords, SignPatientManageRouteVO signPatientManageRouteVO) {
        JSONObject retObj = new JSONObject();
        retObj.fluentPut("code", 0).fluentPut("msg", "成功");
        List<SignPatientManageRouteNode> signPatientManageRouteNodes = signPatientManageRouteNodeMapper.selectNodeByRouteId(signPatientManageRouteVO.getId());
        if (CollectionUtils.isEmpty(signPatientManageRouteNodes)) {
            return retObj;
        }
        SignPatientManageRouteNode signPatientManageRouteNode = signPatientManageRouteNodes.stream().filter(Objects::nonNull).findFirst().orElse(new SignPatientManageRouteNode());
        if (Objects.isNull(signPatientManageRouteNode) || signPatientManageRouteNode.getNodeExecuteStatus().equals(NodeExecuteStatusEnum.EXECUTED.getInfo())) {
            int count = shortMessageSendRecordMapper.selectSendRecordCountByNodeId(signPatientManageRouteNode.getId());
            if (count > 0) {
                return retObj;
            }
        }
        ShortMessageSendRecord shortMessageSendRecord = new ShortMessageSendRecord();
        if (ObjectUtils.isNotEmpty(signPatientManageRouteNode) && signPatientManageRouteNode.getMessagePushSign() == 1) {
            if (data.getSuccess()) {
                // 标记任务执行状态
                signPatientManageRouteNode.setNodeExecuteStatus(NodeExecuteStatusEnum.EXECUTED.getInfo());
                signPatientManageRouteNode.setMessageNodeExecuteResultStatus(NodeExecuteResultStatusEnum.SUCCESS.getInfo());
                shortMessageSendRecord.setErrorStatus(ErrorStatusEnum.success.getValue());
                shortMessageSendRecord.setErrorCode(0L);
            } else {
                // 标记任务执行状态
                signPatientManageRouteNode.setNodeExecuteStatus(NodeExecuteStatusEnum.EXECUTED.getInfo());
                signPatientManageRouteNode.setMessageNodeExecuteResultStatus(NodeExecuteResultStatusEnum.FAILURE.getInfo());
                shortMessageSendRecord.setErrorStatus(ErrorStatusEnum.fail.getValue());
                shortMessageSendRecord.setErrorCode(1L);
                shortMessageSendRecord.setErrMsg(data.getErr_msg());
            }
            shortMessageSendRecord.setSendTime(LocalDateTime.parse(data.getSend_time(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            shortMessageSendRecord.setManageRouteNodeId(signPatientManageRouteNode.getId());
            shortMessageSendRecord.setPatientPhone(data.getPhone_number());
            shortMessageSendRecord.setMessageTemplateId(signPatientManageRouteNode.getMessageTemplateCode());
            shortMessageSendRecord.setMessageNodeContent(signPatientManageRouteNode.getMessageNodeContent());
            shortMessageSendRecord.setMessageType("COMMON");
            if (StringUtils.isNotBlank(data.getSms_size())){
                shortMessageSendRecord.setMessageQuantity(Long.valueOf(data.getSms_size()));
                shortMessageSendRecord.setMessageUnitPrice(new BigDecimal("0.1"));
            }
            shortMessageSendRecord.setCreateBy("system");
            shortMessageSendRecord.setCreateTime(LocalDateTime.now());
            if (Objects.nonNull(shortMessageSendRecord.getMessageUnitPrice()) && Objects.nonNull(shortMessageSendRecord.getMessageQuantity())){
                shortMessageSendRecord.setMessageExpense(shortMessageSendRecord.getMessageUnitPrice().multiply(new BigDecimal(shortMessageSendRecord.getMessageQuantity())));
            }
            shortMessageSendRecords.add(shortMessageSendRecord);
            signPatientManageRouteNodeMapper.updateSignPatientManageRouteNode(signPatientManageRouteNode);
        }
        return retObj;
    }

    @Override
    public Integer updateReadState(Integer readState, List<Integer> ids) {
        log.info("开始修改短信回调数据已读状态");
        JSONObject TaskCallbackUpdateDto = new JSONObject();
        TaskCallbackUpdateDto.fluentPut("ids", ids.toString()).fluentPut("readState", readState);
        HttpEntity<JSONObject> requestEntity = new HttpEntity<>(TaskCallbackUpdateDto);
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> responseEntity = restTemplate.exchange(callBackUrl + "/updateMessageBackReadState", HttpMethod.POST, requestEntity, String.class);
        JSONObject object = JSON.parseObject(responseEntity.getBody());
        if (object == null || object.getInteger("code") == null || object.getInteger("code") != 0) {
            log.info("修改百度外呼回调数据已读状态失败--id：{},原因：{}", ids, object.getString("message"));
            return null;
        }
        log.info("修改百度外呼回调数据已读状态成功--id：{}", ids);
        return 1;
    }

    @Override
    public Integer deleteData() {
        return null;
    }
}
