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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
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.TmsMessageMapper;
import com.prolog.rdc.tms.model.dto.message.MessageCountDTO;
import com.prolog.rdc.tms.model.dto.message.MessageDTO;
import com.prolog.rdc.tms.model.entity.message.TmsMessageModel;
import com.prolog.rdc.tms.model.enums.MessageAlarmTypeEnum;
import com.prolog.rdc.tms.model.enums.MessageNoticeTypeEnum;
import com.prolog.rdc.tms.model.vo.message.MessageQueryVO;
import com.prolog.rdc.tms.model.vo.message.MessageReadAllVO;
import com.prolog.rdc.tms.model.vo.message.PullMessageVO;
import com.prolog.rdc.tms.model.vo.message.ReadMessageVO;
import com.prolog.rdc.tms.service.SysRefdatadService;
import com.prolog.rdc.tms.service.message.MessageService;
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 org.springframework.transaction.annotation.Transactional;

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

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

    @Autowired
    private TmsMessageMapper tmsMessageMapper;

    @Autowired
    private SysRefdatadService sysRefdatadService;

    @Override
    public Page<MessageDTO> query(MessageQueryVO vo) {
        if (StrUtil.isBlank(vo.getNoticeType())) {
            vo.setNoticeType(MessageNoticeTypeEnum.BUSINESS.getCode());
        }
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        Criteria criteria = Criteria.forClass(TmsMessageModel.class);
        Restriction r1 = Restrictions.eq(TmsMessageModel::getReceiveUserId, user.getUserid().toString());
        Restriction r2 = Restrictions.eq(TmsMessageModel::getEnterpriseId, user.getEnterpriseId());
        Restriction r3 = StrUtil.isBlank(vo.getType())?null:Restrictions.eq(TmsMessageModel::getMessageType, vo.getType());
        Restriction r4 = StrUtil.isBlank(vo.getNoticeType())?null:Restrictions.eq(TmsMessageModel::getMessageNoticeType, vo.getNoticeType());
        Restriction r5 = StrUtil.isBlank(vo.getWhetherRead())?null:Restrictions.eq(TmsMessageModel::getWhetherRead, vo.getWhetherRead());
        criteria.setRestriction(Restrictions.and(r1,r2,r3,r4,r5));
        criteria.setOrder(Order.newInstance().asc(TmsMessageModel::getWhetherRead).desc(TmsMessageModel::getUpdatetime));
        PageHelper.startPage(vo.getPageNum(), vo.getPageSize());
        List<TmsMessageModel> tmsMessageModelList = tmsMessageMapper.findByCriteria(criteria);
        List<MessageDTO> result = convertToMessageDTOList(tmsMessageModelList);
        Page<MessageDTO> page = PageUtils.getPage(result);
        if (tmsMessageModelList instanceof com.github.pagehelper.Page) {
            com.github.pagehelper.Page<TmsMessageModel> p0 = (com.github.pagehelper.Page<TmsMessageModel>) tmsMessageModelList;
            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 MessageDTO findById(Long messageId) {
        TmsMessageModel messageModel = tmsMessageMapper.findById(messageId, TmsMessageModel.class);
        if (ObjectUtil.isNull(messageModel)) {
            throw new BizException("消息不存在，id=" + messageId);
        }
        // 消息类型
        List<Map<String, Object>> messageType = sysRefdatadService.getDropDownById(DataDictionaryConstant.MESSAGE_TYPE, null, null, null);
        // 消息推送方式
        List<Map<String, Object>> messageSendType = sysRefdatadService.getDropDownById(DataDictionaryConstant.MESSAGE_SEND_TYPE, null, null, null);
        // 预警消息类型
        List<Map<String, Object>> messageAlarmType = sysRefdatadService.getDropDownById(MessageAlarmTypeEnum.MESSAGE_ALARM_TYPE, null, null, null);
        return convertToMessageDTO(messageModel, messageType, messageSendType, messageAlarmType);
    }

    @Override
    public Long countMessage(MessageQueryVO vo) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        Criteria criteria = Criteria.forClass(TmsMessageModel.class);
        Restriction r1 = Restrictions.eq(TmsMessageModel::getReceiveUserId, user.getUserid().toString());
        Restriction r2 = Restrictions.eq(TmsMessageModel::getEnterpriseId, user.getEnterpriseId());
        Restriction r3 = StrUtil.isBlank(vo.getType())?null:Restrictions.eq(TmsMessageModel::getMessageType, vo.getType());
        Restriction r4 = StrUtil.isBlank(vo.getNoticeType())?null:Restrictions.eq(TmsMessageModel::getMessageNoticeType, vo.getNoticeType());
        Restriction r5 = StrUtil.isBlank(vo.getWhetherRead())?null:Restrictions.eq(TmsMessageModel::getWhetherRead, vo.getWhetherRead());
        criteria.setRestriction(Restrictions.and(r1,r2,r3,r4,r5));
        return tmsMessageMapper.findCountByCriteria(criteria);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void read(ReadMessageVO vo) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        ToolKits.isParamNull(vo, "入参不能为空");
        ToolKits.isParamNull(vo.getIdList(), "主键集合不能为空");
        List<TmsMessageModel> tmsMessageModelList =
                tmsMessageMapper.findByIds(TmsMessageModel.class, vo.getIdList().toArray(), null);
        if (CollectionUtil.isEmpty(tmsMessageModelList)) {
            throw new BizException("消息不存在");
        }
        tmsMessageModelList.forEach(tmsMessageModel -> {
            if (!DataDictionaryConstant.WHETHER_READ_Y.equals(tmsMessageModel.getWhetherRead())) {
                tmsMessageModel.setUpdatetime(DateUtil.date());
                tmsMessageModel.setUpdateperson(user.getNickname());
                tmsMessageModel.setReadTime(DateUtil.date());
                tmsMessageModel.setWhetherRead(DataDictionaryConstant.WHETHER_READ_Y);
                tmsMessageMapper.update(tmsMessageModel);
            }
        });
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void readAll(MessageReadAllVO vo) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        vo.setReceiveUserId(user.getUserid());
        vo.setUpdatePerson(user.getNickname());
        tmsMessageMapper.readAll(vo);
    }

    @Override
    public List<MessageDTO> pullMessage(PullMessageVO vo) {
        if (ObjectUtil.isNull(vo.getEndDate())) {
            vo.setEndDate(DateUtil.date());
        }
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        Criteria criteria = Criteria.forClass(TmsMessageModel.class);
        Restriction r1 = Restrictions.eq("receiveUserId", user.getUserid().toString());
        Restriction r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
        Restriction r3 = Restrictions.ge(TmsMessageModel::getSendTime, DateUtil.offsetSecond(vo.getEndDate(), -1 * vo.getInterval()));
        Restriction r4 = Restrictions.le(TmsMessageModel::getSendTime, vo.getEndDate());
        criteria.setRestriction(Restrictions.and(r1,r2,r3,r4));
        List<TmsMessageModel> tmsMessageModelList = tmsMessageMapper.findByCriteria(criteria);
        return convertToMessageDTOList(tmsMessageModelList);
    }

    @Override
    public MessageCountDTO countByMessageType() {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        MessageCountDTO messageCountDTO = new MessageCountDTO();
        Long pickUpNumber = tmsMessageMapper.countByMessageType(MessageNoticeTypeEnum.ALARM.getCode(), MessageAlarmTypeEnum.PICK_UP.getCode(), user.getEnterpriseId(), user.getUserid().toString());
        Long deliveryNumber = tmsMessageMapper.countByMessageType(MessageNoticeTypeEnum.ALARM.getCode(), MessageAlarmTypeEnum.DELIVERY.getCode(), user.getEnterpriseId(), user.getUserid().toString());
        Long receiptNumber = tmsMessageMapper.countByMessageType(MessageNoticeTypeEnum.ALARM.getCode(), MessageAlarmTypeEnum.RECEIPT.getCode(), user.getEnterpriseId(), user.getUserid().toString());
        Long temperatureNumber = tmsMessageMapper.countByMessageType(MessageNoticeTypeEnum.ALARM.getCode(), MessageAlarmTypeEnum.TEMPERATURE.getCode(), user.getEnterpriseId(), user.getUserid().toString());
        messageCountDTO.setPickUpNumber(pickUpNumber);
        messageCountDTO.setDeliveryNumber(deliveryNumber);
        messageCountDTO.setReceiptNumber(receiptNumber);
        messageCountDTO.setTemperatureNumber(temperatureNumber);
        return messageCountDTO;
    }

    /**
     * convertToMessageDTO
     * @param tmsMessageModel
     * @param messageType
     * @param messageSendType
     * @param messageAlarmType
     * @return
     */
    private MessageDTO convertToMessageDTO(TmsMessageModel tmsMessageModel,
                                           List<Map<String, Object>> messageType,
                                           List<Map<String, Object>> messageSendType,
                                           List<Map<String, Object>> messageAlarmType) {
        MessageDTO messageDTO = BeanUtil.copyProperties(tmsMessageModel, MessageDTO.class);
        messageDTO.setMessageTypeName(PublicMethods.change(messageType, messageDTO.getMessageType()));
        if (StrUtil.isBlank(messageDTO.getMessageTypeName())) {
            messageDTO.setMessageTypeName(PublicMethods.change(messageAlarmType, messageDTO.getMessageType()));
        }
        messageDTO.setMessageSendTypeName(Arrays.stream(messageDTO.getMessageSendType().split(",")).map(sendType ->
                PublicMethods.change(messageSendType, sendType)).collect(Collectors.joining(",")));
        return messageDTO;
    }

    /**
     * convertToMessageDTOList
     * @param tmsMessageModelList
     * @return
     */
    private List<MessageDTO> convertToMessageDTOList(List<TmsMessageModel> tmsMessageModelList) {
        List<MessageDTO> result = Lists.newArrayList();
        if (CollectionUtil.isNotEmpty(tmsMessageModelList)) {
            // 消息类型
            List<Map<String, Object>> messageType = sysRefdatadService.getDropDownById(DataDictionaryConstant.MESSAGE_TYPE, null, null, null);
            // 消息推送方式
            List<Map<String, Object>> messageSendType = sysRefdatadService.getDropDownById(DataDictionaryConstant.MESSAGE_SEND_TYPE, null, null, null);
            // 预警消息类型
            List<Map<String, Object>> messageAlarmType = sysRefdatadService.getDropDownById(MessageAlarmTypeEnum.MESSAGE_ALARM_TYPE, null, null, null);
            result = tmsMessageModelList.stream().map(tmsMessageModel -> convertToMessageDTO(tmsMessageModel, messageType, messageSendType, messageAlarmType))
                    .collect(Collectors.toList());
        }
        return result;
    }

}
