package com.prolog.rdc.tms.service.message.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;
import com.prolog.common.util.ToolKits;
import com.prolog.framework.core.exception.BizException;
import com.prolog.framework.core.pojo.Page;
import com.prolog.framework.core.restriction.Criteria;
import com.prolog.framework.core.restriction.Order;
import com.prolog.framework.core.restriction.Restriction;
import com.prolog.framework.core.restriction.Restrictions;
import com.prolog.framework.dao.util.PageUtils;
import com.prolog.product.core.framework.entity.UserEntity;
import com.prolog.product.core.framework.util.PlgFxUsrUtils;
import com.prolog.rdc.tms.constant.DataDictionaryConstant;
import com.prolog.rdc.tms.dao.mapper.TmsMessageSendLogMapper;
import com.prolog.rdc.tms.model.dto.message.ChannelMessageDTO;
import com.prolog.rdc.tms.model.dto.message.MessageSendLogDTO;
import com.prolog.rdc.tms.model.entity.message.TmsMessageSendLogModel;
import com.prolog.rdc.tms.model.enums.MessageAlarmTypeEnum;
import com.prolog.rdc.tms.model.enums.MessageNoticeTypeEnum;
import com.prolog.rdc.tms.model.vo.message.MessageSendLogQueryVO;
import com.prolog.rdc.tms.model.vo.message.RetrySendLogVO;
import com.prolog.rdc.tms.service.SysRefdatadService;
import com.prolog.rdc.tms.service.message.MessageChannel;
import com.prolog.rdc.tms.service.message.MessageSendLogService;
import com.prolog.rdc.tms.util.PublicMethods;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author hongbo.pan
 * @date 2022/11/16
 */
@Slf4j
@Service
public class MessageSendLogServiceImpl implements MessageSendLogService {

    @Autowired
    private TmsMessageSendLogMapper tmsMessageSendLogMapper;

    @Autowired
    private SysRefdatadService sysRefdatadService;

    @Autowired
    private MessageChannelFactory factory;

    @Override
    public Page<MessageSendLogDTO> query(MessageSendLogQueryVO vo) {
        if (StrUtil.isBlank(vo.getNoticeType())) {
            vo.setNoticeType(MessageNoticeTypeEnum.BUSINESS.getCode());
        }
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        Criteria criteria = Criteria.forClass(TmsMessageSendLogModel.class);
        Restriction r1 = StrUtil.isBlank(vo.getMessageName())?null: Restrictions.like("messageName", "%"+vo.getMessageName()+"%");
        Restriction r2 = StrUtil.isBlank(vo.getMessageType())?null:Restrictions.eq("messageType", vo.getMessageType());
        Restriction r3 = StrUtil.isBlank(vo.getSendType())?null:Restrictions.like("sendType", "%"+vo.getSendType()+"%");
        Restriction r4 = StrUtil.isBlank(vo.getOrderType())?null:Restrictions.eq("orderType", vo.getOrderType());
        Restriction r5 = StrUtil.isBlank(vo.getOrderNo())?null:Restrictions.like("orderNo", "%"+vo.getOrderNo()+"%");
        Restriction r6 = StrUtil.isBlank(vo.getSendStatus())?null:Restrictions.eq("sendStatus", vo.getSendStatus());
        Restriction r7 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
        Restriction r8 = StrUtil.isBlank(vo.getNoticeType())?null:Restrictions.eq(TmsMessageSendLogModel::getMessageNoticeType, vo.getNoticeType());
        criteria.setRestriction(Restrictions.and(r1,r2,r3,r4,r5,r6,r7,r8));
        criteria.setOrder(Order.newInstance().desc("updatetime"));
        PageHelper.startPage(vo.getPageNum(), vo.getPageSize());
        List<TmsMessageSendLogModel> tmsMessageSendLogModelList = tmsMessageSendLogMapper.findByCriteria(criteria);
        List<MessageSendLogDTO> result = Lists.newArrayList();
        if (CollectionUtil.isNotEmpty(tmsMessageSendLogModelList)) {
            // 消息类型
            List<Map<String, Object>> messageType = sysRefdatadService.getDropDownById(DataDictionaryConstant.MESSAGE_TYPE, null, null, null);
            // 预警消息类型
            List<Map<String, Object>> messageAlarmType = sysRefdatadService.getDropDownById(MessageAlarmTypeEnum.MESSAGE_ALARM_TYPE, null, null, null);
            // 消息推送方式
            List<Map<String, Object>> messageSendType = sysRefdatadService.getDropDownById(DataDictionaryConstant.MESSAGE_SEND_TYPE, null, null, null);
            // 消息单据类型
            List<Map<String, Object>> messageOrderType = sysRefdatadService.getDropDownById(DataDictionaryConstant.MESSAGE_ORDER_TYPE, null, null, null);
            // 消息日志状态
            List<Map<String, Object>> messageSendLogStatus = sysRefdatadService.getDropDownById(DataDictionaryConstant.MESSAGE_SEND_LOG_STATUS, null, null, null);
            result = tmsMessageSendLogModelList.stream().map(tmsMessageSendLogModel ->
                            convertToMessageSendLogDTO(tmsMessageSendLogModel, messageType, messageSendType,
                                    messageOrderType, messageSendLogStatus, messageAlarmType)).collect(Collectors.toList());
        }
        Page<MessageSendLogDTO> page = PageUtils.getPage(result);
        if (tmsMessageSendLogModelList instanceof com.github.pagehelper.Page) {
            com.github.pagehelper.Page<TmsMessageSendLogModel> p0 = (com.github.pagehelper.Page<TmsMessageSendLogModel>) tmsMessageSendLogModelList;
            page.setPageCount(p0.getPages());
            page.setPageNum(p0.getPageNum());
            page.setPageSize(p0.getPageSize());
            page.setTotalCount(p0.getTotal());
            page.setStartRow(p0.getStartRow());
            page.setEndRow(p0.getEndRow());
        }
        return page;
    }

    @Override
    public void retry(RetrySendLogVO vo) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        ToolKits.isParamNull(vo, "入参不能为空");
        ToolKits.isParamNull(vo.getIdList(), "主键集合不能为空");
        List<TmsMessageSendLogModel> tmsMessageSendLogModelList =
                tmsMessageSendLogMapper.findByIds(TmsMessageSendLogModel.class, vo.getIdList().toArray(new Long[0]), null);
        if (CollectionUtil.isEmpty(tmsMessageSendLogModelList)) {
            throw new BizException("消息日志不存在");
        }
        tmsMessageSendLogModelList.forEach(tmsMessageSendLogModel -> {
            tmsMessageSendLogModel.setUpdatetime(new Date());
            tmsMessageSendLogModel.setUpdateperson(user.getNickname());
            tmsMessageSendLogModel.setRetryTime(new Date());
            tmsMessageSendLogModel.setRetryCount(tmsMessageSendLogModel.getRetryCount() + 1L);
            try {
                ChannelMessageDTO channelMessageDTO = JSON.parseObject(tmsMessageSendLogModel.getRequestParam(), ChannelMessageDTO.class);
                MessageChannel channel = factory.getChannel(tmsMessageSendLogModel.getSendType());
                channel.send(channelMessageDTO);
                tmsMessageSendLogModel.setSendStatus(DataDictionaryConstant.MESSAGE_SEND_LOG_SUCCESS);
            } catch (Exception e) {
                tmsMessageSendLogModel.setSendStatus(DataDictionaryConstant.MESSAGE_SEND_LOG_FAIL);
                tmsMessageSendLogModel.setErrorMsg(ExceptionUtil.stacktraceToString(e));
                log.error("topic={},title={}", "MessageSendLogServiceImpl", "retry", e);
            }
            tmsMessageSendLogMapper.update(tmsMessageSendLogModel);
        });
    }

    /**
     * convertToMessageSendLogDTO
     * @param tmsMessageSendLogModel
     * @param messageType
     * @param messageSendType
     * @param messageOrderType
     * @param messageSendLogStatus
     * @param messageAlarmType
     * @return
     */
    private MessageSendLogDTO convertToMessageSendLogDTO(TmsMessageSendLogModel tmsMessageSendLogModel,
                                           List<Map<String, Object>> messageType,List<Map<String, Object>> messageSendType,
                                             List<Map<String, Object>> messageOrderType,List<Map<String, Object>> messageSendLogStatus,
                                                         List<Map<String, Object>> messageAlarmType) {
        MessageSendLogDTO messageSendLogDTO = BeanUtil.copyProperties(tmsMessageSendLogModel, MessageSendLogDTO.class);
        messageSendLogDTO.setMessageTypeName(PublicMethods.change(messageType, messageSendLogDTO.getMessageType()));
        if (StrUtil.isBlank(messageSendLogDTO.getMessageTypeName())) {
            messageSendLogDTO.setMessageTypeName(PublicMethods.change(messageAlarmType, messageSendLogDTO.getMessageType()));
        }
        messageSendLogDTO.setSendTypeName(PublicMethods.change(messageSendType, messageSendLogDTO.getSendType()));
        messageSendLogDTO.setOrderTypeName(PublicMethods.change(messageOrderType, messageSendLogDTO.getOrderType()));
        messageSendLogDTO.setSendStatusName(PublicMethods.change(messageSendLogStatus, messageSendLogDTO.getSendStatus()));
        return messageSendLogDTO;
    }

}
