package com.dayou.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.dayou.common.BaseEntity;
import com.dayou.dto.OrderReportDTO;
import com.dayou.dto.ReportDTO;
import com.dayou.dto.WareHouseDTO;
import com.dayou.dto.WorkNodeCommit;
import com.dayou.entity.*;
import com.dayou.enums.MainBusinessEnum;
import com.dayou.enums.UserTypeEnum;
import com.dayou.mapper.MajorProductionMapper;
import com.dayou.mapper.MessageMapper;
import com.dayou.message.MessageTypeEnum;
import com.dayou.message.bo.BusinessMessageBO;
import com.dayou.message.bo.SystemMessageBO;
import com.dayou.message.handler.BusinessMessageHandler;
import com.dayou.message.handler.SystemMessageHandler;
import com.dayou.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dayou.service.workflow.IWorkTaskRecordService;
import com.dayou.utils.DateUtils;
import com.dayou.utils.LoginContext;
import com.dayou.vo.CommissionDeclareVO;
import com.dayou.vo.ItemVO;
import com.dayou.vo.MajorProductionVO;
import com.dayou.vo.TaskReminderVO;
import com.dayou.websocket.WebSocketServer;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;

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

import static com.dayou.enums.BusinessReplyEnum.MARKET_LOG_REPLY;
import static com.dayou.enums.BusinessReplyEnum.MARKET_VISIT_REPLY;
import static com.dayou.message.MessageTitle.*;
import static com.dayou.message.MessageTitle.MAJOR_DECLARE_REMIND;
import static com.dayou.message.MessageTypeEnum.*;
import static com.dayou.utils.DateUtils.YYYY_MM_DD_HH_MM_SS;

/**
 * <p>
 * 消息 服务实现类
 * </p>
 *
 * @author wucl
 * @since 2023-06-30
 */
@Service
public class MessageServiceImpl extends ServiceImpl<MessageMapper, Message> implements IMessageService {

    @Autowired
    private BusinessMessageHandler businessMessageHandler;

    @Autowired
    private SystemMessageHandler systemMessageHandler;

    @Autowired
    private ICommissionDeclareService commissionDeclareService;

    @Autowired
    private IMajorService majorService;

    @Autowired
    private IMajorProductionService majorProductionService;

    @Autowired
    private IUserService userService;

    @Autowired
    private MajorProductionMapper majorProductionMapper;

    @Autowired
    private IMajorProductionAllotService majorProductionAllotService;

    @Autowired
    private IWorkTaskRecordService workTaskRecordService;

    @Autowired
    private WebSocketServer webSocketServer;


    @Override
    public Boolean packagingBusinessMessage(BusinessReply originalBO) {
        BusinessMessageBO messageBO = new BusinessMessageBO();
        messageBO.setReceiver(originalBO.getReceiverId());
        String bizType = originalBO.getBizType().equals(MARKET_VISIT_REPLY.name())?MARKET_VISIT_REPLY.getName(): MARKET_LOG_REPLY.getName();
        messageBO.setTitle(BUSINESS_MESSAGE_TITLE.replace("x", bizType));
        messageBO.setMessage(originalBO.getContent());
        messageBO.setParams(JSON.toJSONString(originalBO));
        messageBO.setSender(originalBO.getReplierId());
        messageBO.setType(BUSINESS.name());
        return businessMessageHandler.sendMessage(messageBO);
    }

    @Override
    public Boolean packagingSettleMessage(Set<Long> userIds) {
        Set<SystemMessageBO> settleMessages = userIds.stream().map(x -> {
            SystemMessageBO systemMessageBO = new SystemMessageBO();
            systemMessageBO.setTitle(SYSTEM_MESSAGE_TITLE.replace("x", SETTLE.getName()));
            systemMessageBO.setMessage(SETTLE_MESSAGE_CONTENT);
            systemMessageBO.setReceiver(x);
            systemMessageBO.setType(SETTLE.name());
            return systemMessageBO;
        }).collect(Collectors.toSet());
        if (CollectionUtils.isNotEmpty(settleMessages)){
            return systemMessageHandler.sendMessage(settleMessages);
        }
        return Boolean.FALSE;
    }

    @Override
    public Boolean packagingMajorDeclareRemind(Long declareId) {
        BusinessMessageBO messageBO = new BusinessMessageBO();
        CommissionDeclareVO declareVO = new CommissionDeclareVO();
        CommissionDeclare originDeclare = commissionDeclareService.getById(declareId);
        String businessType = originDeclare.getBusinessType();


        String template = MAJOR_DECLARE_REMIND_CONTENT;
        declareVO.setId(originDeclare.getId());

        Major order = majorService.getOne(new LambdaQueryWrapper<Major>().select(Major::getClientManagerId, Major::getPrincipalId, Major::getOrderId, Major::getName)
                .eq(BaseEntity::getId, originDeclare.getBusinessId()));
        declareVO.setOrderName(order.getName());
        if (originDeclare.getProductionId()!=null){
            MajorProduction production = majorProductionService.getOne(new LambdaQueryWrapper<MajorProduction>().select(MajorProduction::getReportNo, MajorProduction::getName)
                    .eq(BaseEntity::getId, originDeclare.getProductionId()));
            template = template.replace("name",production.getName());
            declareVO.setName(production.getName());
            declareVO.setReportNo(production.getReportNo());
        }else {
            template = template.replace("name",order.getName());
        }
        messageBO.setType(MessageTypeEnum.MAJOR_DECLARE_REMIND.name());
        messageBO.setTitle(MAJOR_DECLARE_REMIND);
        messageBO.setParams(JSON.toJSONString(declareVO));
        if (MainBusinessEnum.COMMISSION_DECLARE_MAJOR_EVALUATE.name().equals(businessType)){
            //评估人员向市场人员发 已申报情况不发送消息
            int count = commissionDeclareService.count(new LambdaQueryWrapper<CommissionDeclare>()
                    .eq(CommissionDeclare::getBusinessType, MainBusinessEnum.COMMISSION_DECLARE_MAJOR_MARKET.name())
                    .eq(CommissionDeclare::getBusinessId, originDeclare.getBusinessId())
                    .eq(originDeclare.getProductionId()!=null,CommissionDeclare::getProductionId,originDeclare.getProductionId()));

            if (count>0){
                return Boolean.FALSE;
            }
            messageBO.setSender(originDeclare.getDeclareUserId());
            messageBO.setReceiver(order.getClientManagerId());
            String marketer = userService.getOne(new LambdaQueryWrapper<User>().select(User::getName).eq(BaseEntity::getId, order.getClientManagerId())).getName();
            template  = marketer + template;
            messageBO.setMessage(template);
            declareVO.setBusinessType(MainBusinessEnum.COMMISSION_DECLARE_MAJOR_MARKET.name());

        }
        if (MainBusinessEnum.COMMISSION_DECLARE_MAJOR_MARKET.name().equals(businessType)){
            //评估人员向评估人员发
            int count = commissionDeclareService.count(new LambdaQueryWrapper<CommissionDeclare>()
                    .eq(CommissionDeclare::getBusinessType, MainBusinessEnum.COMMISSION_DECLARE_MAJOR_EVALUATE.name())
                    .eq(CommissionDeclare::getBusinessId, originDeclare.getBusinessId())
                    .eq(originDeclare.getProductionId()!=null,CommissionDeclare::getProductionId,originDeclare.getProductionId()));
            if (count>0){
                return Boolean.FALSE;
            }
            messageBO.setSender(originDeclare.getDeclareUserId());
            if (order.getPrincipalId()==null){
                return Boolean.FALSE;
            }
            messageBO.setReceiver(order.getPrincipalId());
            String evaluator = userService.getOne(new LambdaQueryWrapper<User>().select(User::getName).eq(BaseEntity::getId, order.getPrincipalId())).getName();
            template  = evaluator + template;
            messageBO.setMessage(template);
            declareVO.setBusinessType(MainBusinessEnum.COMMISSION_DECLARE_MAJOR_EVALUATE.name());
        }
        messageBO.setParams(JSON.toJSONString(declareVO));
        return businessMessageHandler.sendMessage(messageBO);
    }

    @Override
    public List<Message> messageRedPoint() {
        Long currentUserId = LoginContext.getCurrentUserId();
        List<Message> list = this.list(new LambdaQueryWrapper<Message>().eq(Message::getReceiver, currentUserId)
                .eq(Message::getIsRead, Boolean.FALSE).orderByDesc(BaseEntity::getCreated));
        return list;
    }

    @Override
    public Boolean updateRead(Long id) {
        return this.update(new LambdaUpdateWrapper<Message>().eq(BaseEntity::getId,id).set(Message::getIsRead,Boolean.TRUE));
    }

    @Override
    public void packagingEvaluateRemind(List<ItemVO> completedNotEvaluateItem) {
        Set<SystemMessageBO> collect = completedNotEvaluateItem.stream().map(x -> {
            SystemMessageBO systemMessageBO = new SystemMessageBO();
            systemMessageBO.setType(EVALUATE_REMIND.name());
            systemMessageBO.setTitle(SYSTEM_MESSAGE_TITLE.replace("x", EVALUATE_REMIND.getName()));
            systemMessageBO.setMessage(EVALUATE_REMIND_CONTENT.replace("x", x.getName()));
            systemMessageBO.setParams(JSON.toJSONString(x));
            systemMessageBO.setReceiver(x.getUserId());
            return systemMessageBO;
        }).collect(Collectors.toSet());
        systemMessageHandler.sendMessage(collect);
    }

    @Override
    public Boolean allRead() {
        Long currentUserId = LoginContext.getCurrentUserId();
        return this.update(new LambdaUpdateWrapper<Message>().eq(Message::getReceiver,currentUserId).set(Message::getIsRead,true));
    }

    @Override
    public void packagingMajorOutRepertoryRemind(WareHouseDTO wareHouseDTO) {
        MajorProductionVO majorProductionVO = majorProductionMapper.getMajorProductionById(wareHouseDTO.getProductionId());
        SystemMessageBO systemMessageBO = new SystemMessageBO();
        systemMessageBO.setReceiver(majorProductionVO.getClientManagerId());
        systemMessageBO.setMessage(MAJOR_PRODUCTION_OUT_CONTENT.replace("reportNo",majorProductionVO.getReportNo()));
        systemMessageBO.setTitle(MAJOR_OUT_REPERTORY_REMIND.getName());
        systemMessageBO.setType(MAJOR_OUT_REPERTORY_REMIND.name());
        systemMessageBO.setParams(JSON.toJSONString(majorProductionVO));
        systemMessageHandler.sendMessage(systemMessageBO);
    }

    @Override
    public void packagingMajorAllotCommissionRemind(List<OrderReportDTO> list) {
        for (OrderReportDTO orderReportDTO : list){
            List<MajorProductionAllot> allots = majorProductionAllotService.list(new LambdaQueryWrapper<MajorProductionAllot>().eq(MajorProductionAllot::getMajorProductionId, orderReportDTO.getId())
                    .eq(MajorProductionAllot::getUserType, UserTypeEnum.EVALUATE.name()).eq(BaseEntity::getDeleted, Boolean.FALSE));
            if (CollectionUtil.isEmpty(allots)){
                MajorProductionVO majorProductionVO = majorProductionMapper.getMajorProductionById(orderReportDTO.getId());
                SystemMessageBO systemMessageBO = new SystemMessageBO();
                systemMessageBO.setReceiver(majorProductionVO.getDepartmentLeaderId());
                systemMessageBO.setMessage(MAJOR_ALLOT_COMMISSION_CONTENT.replace("reportNo",majorProductionVO.getReportNo()));
                systemMessageBO.setTitle(MAJOR_ALLOT_COMMISSION_REMIND1.getName());
                systemMessageBO.setType(MAJOR_ALLOT_COMMISSION_REMIND1.name());
                systemMessageBO.setParams(JSON.toJSONString(majorProductionVO));
                systemMessageHandler.sendMessage(systemMessageBO);
            }
        }

    }

    @Override
    public void packagingMajorAllotCommissionRemind1(OrderReportDTO orderReportDTO) {
        List<ReportDTO> reports = orderReportDTO.getReports();
        if (CollectionUtil.isNotEmpty(reports)){
            List<Long> productionIds = reports.stream().map(ReportDTO::getId).collect(Collectors.toList());
            List<MajorProductionAllot> allots = majorProductionAllotService.list(new LambdaQueryWrapper<MajorProductionAllot>().in(MajorProductionAllot::getMajorProductionId, productionIds)
                    .eq(MajorProductionAllot::getUserType, UserTypeEnum.EVALUATE.name()).eq(BaseEntity::getDeleted, Boolean.FALSE));
            if (CollectionUtil.isEmpty(allots)){
                productionIds.stream().forEach(x->{
                    MajorProductionVO majorProductionVO = majorProductionMapper.getMajorProductionById(x);
                    SystemMessageBO systemMessageBO = new SystemMessageBO();
                    systemMessageBO.setReceiver(majorProductionVO.getDepartmentLeaderId());
                    systemMessageBO.setMessage(MAJOR_ALLOT_COMMISSION_CONTENT.replace("reportNo",majorProductionVO.getReportNo()));
                    systemMessageBO.setTitle(MAJOR_ALLOT_COMMISSION_REMIND1.getName());
                    systemMessageBO.setType(MAJOR_ALLOT_COMMISSION_REMIND1.name());
                    systemMessageBO.setParams(JSON.toJSONString(majorProductionVO));
                    systemMessageHandler.sendMessage(systemMessageBO);
                });

            }
        }


    }

    @Override
    public void packagingNodeTodoReminder(WorkNodeCommit commit) {
        Long instanceNodeId = commit.getInstanceNodeId();
        String businessSubId = commit.getBusinessSubId();
        String businessMinId = commit.getBusinessMinId();
        //
        TaskReminderVO taskReminderVO = workTaskRecordService.getTaskReminderInfo(instanceNodeId);
        //根据处理人查询
        Long handlerId = workTaskRecordService.getHandlerIdByLastNode(taskReminderVO.getBusiness(), taskReminderVO.getBusinessId(), businessSubId, businessMinId);
        if (handlerId != null){
            Message message = new Message();
            message.setTitle(NODE_TODO_REMINDER.getName());
            message.setReceiver(handlerId);
            message.setParams(JSON.toJSONString(taskReminderVO));
            message.setSender(1L);
            message.setType(NODE_TODO_REMINDER.name());
            message.setMessage(new StringBuilder(taskReminderVO.getUser()).append("提交").append(taskReminderVO.getBusinessType())
                    .append(StrUtil.isNotBlank(taskReminderVO.getNo())?taskReminderVO.getNo():"").append("的新的流程待办，请及时处理。").toString());
            this.save(message);
            taskReminderVO.setCreated(DateUtils.parseDateToStr(YYYY_MM_DD_HH_MM_SS,message.getCreated()));
            taskReminderVO.setHandlerId(handlerId);
            //发送websocket
            webSocketServer.sendNodeReminder(taskReminderVO);
        }
    }

    @Override
    public void sendWebSocket() {
        TaskReminderVO taskReminderVO = new TaskReminderVO();
        taskReminderVO.setId(RandomUtil.randomLong());
        taskReminderVO.setCreated(DateUtils.parseDateToStr(YYYY_MM_DD_HH_MM_SS,new Date()));
        taskReminderVO.setHandlerId(1L);
        taskReminderVO.setUser("管理员");
        taskReminderVO.setNo("2025010001");
        taskReminderVO.setBusinessType("大中型业务");
        webSocketServer.sendNodeReminder(taskReminderVO);
    }
}
