package com.junmp.jyzb.listener;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.junmp.junmpProcess.dto.ApplyTypeDto;
import com.junmp.junmpProcess.dto.UserListDTO;
import com.junmp.junmpProcess.dto.json.UserInfo;
import com.junmp.junmpProcess.mapper.OrgUserMapper;
import com.junmp.jyzb.api.bean.query.inAndOutRecordReq.DetailJsonReq;
import com.junmp.jyzb.api.bean.req.UpdateOrderDetailReq;
import com.junmp.jyzb.api.bean.req.UpdateOrderReq;
import com.junmp.jyzb.api.bean.req.UpdateReassignmentReq;
import com.junmp.jyzb.api.constant.JYZBConstant;
import com.junmp.jyzb.cache.MsgRedisCache;
import com.junmp.jyzb.entity.*;
import com.junmp.jyzb.service.*;
import com.junmp.jyzb.utils.DateTimeUtil;
import com.junmp.jyzb.utils.RabbitMQSendMsg;
import com.junmp.v2.common.util.BeanPlusUtil;
import com.junmp.v2.message.api.MessageApi;
import com.junmp.v2.message.api.bean.req.MessageSendReq;
import com.junmp.v2.sys.user.entity.SysUserOrg;
import com.junmp.v2.sys.user.service.SysUserOrgService;
import lombok.SneakyThrows;
import org.flowable.bpmn.model.Process;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.delegate.event.AbstractFlowableEngineEventListener;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.variable.api.history.HistoricVariableInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

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

import static com.junmp.junmpProcess.common.CommonConstants.*;


@Component
public class GlobalEndListener extends AbstractFlowableEngineEventListener {
    @Resource
    public OrderMainService orderMainService;

    @Resource
    public OrderDetailService orderDetailService;
    @Resource
    private HistoryService historyService;

    @Resource
    private BusFormService busFormService;

    @Resource
    private PolicemanService policemanService;
    @Resource
    private ReassignmentService reassignmentService;

    @Resource
    private LogSummaryService logSummaryService;
    @Resource
    private LogDetailService logDetailService;

    @Resource
    private MessageApi messageApi;
    @Resource
    private BussinessInventoryService bussinessInventoryService;
    @Autowired
    private RabbitMQSendMsg MQ;

    @Resource
    private OrgUserMapper orgUserMapper;

    @Resource
    private SysUserOrgService sysUserOrgService;
    @Resource
    private RepositoryService repositoryService;

    @Resource
    private EquipmentTypeService equipmentTypeService;

    @Resource
    private EquipmentSizeService equipmentSizeService;

    @Resource
    private SupplierTypeService supplierTypeService;

    @Resource
    private MsgRedisCache redisCache;

    @Transactional(rollbackFor = Exception.class)
    @SneakyThrows
    @Override
    public void processCompleted(FlowableEngineEntityEvent event) {


        if (event.getType() == FlowableEngineEventType.PROCESS_COMPLETED) {
            // 获取流程实例ID
            String processInstanceId = event.getProcessInstanceId();

            Process mainProcess = repositoryService.getBpmnModel(event.getProcessDefinitionId()).getMainProcess();
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                    .processInstanceId(processInstanceId)
                    .includeProcessVariables()
                    .singleResult();
            // 获取流程定义ID
            String processDefinitionId = event.getProcessDefinitionId();
            //如果redis中存在该流程id的消息，那么不执行，否则执行
            String objJson= redisCache.get(processDefinitionId);
            if (objJson==null) {
                List<HistoricVariableInstance> typeOrder = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).variableName("typeOrder").list();
                String OrderName = "";
                String Type = "";
                if (typeOrder.size() > 0) {

                    Type = typeOrder.get(0).getValue().toString();
                    if (Type.equals("workOrder") || Type.equals("quickOrder")) {
                        OrderMain existOrder = orderMainService.getOne(new LambdaQueryWrapper<OrderMain>()
                                .eq(OrderMain::getProcessId, processInstanceId));
                        existOrder.setExamineState("finished");
                        existOrder.setOrderState("ready");
                        UpdateOrderReq updateOrderReq = new UpdateOrderReq();
                        BeanPlusUtil.copyProperties(existOrder, updateOrderReq);
                        List<OrderDetail> list = orderDetailService.list(new LambdaQueryWrapper<OrderDetail>()
                                .eq(OrderDetail::getOrderId, updateOrderReq.getId()));
                        updateOrderReq.setId(existOrder.getId());
                        existOrder.setActualQuantity(0);
                        orderMainService.updateById(existOrder);
//                        orderMainService.ChangeOrderState(updateOrderReq);
                        List<UpdateOrderDetailReq> collect = list.stream().map(orderDetail -> {
                            UpdateOrderDetailReq updateOrderDetailReq = new UpdateOrderDetailReq();
                            BeanPlusUtil.copyProperties(orderDetail, updateOrderDetailReq);
                            if (ObjectUtil.isNotNull(orderDetail.getProductionDate())) {
                                SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
                                updateOrderDetailReq.setProductionDate(format.format(orderDetail.getProductionDate()));
                            }
                            orderDetail.setActualNum(0);
                            orderDetail.setModifyQuantity(0);
                            return updateOrderDetailReq;
                        }).collect(Collectors.toList());
                        orderDetailService.updateBatchById(list);
                        updateOrderReq.setDetailList(collect);
                        //将单据上传到rabbitmq
                        orderMainService.AddFinishOrder(updateOrderReq);

                    } else if (Type.equals("bussinessOrder")) {
                        BusForm busForm = busFormService.getOne(new LambdaQueryWrapper<BusForm>()
                                .eq(BusForm::getProcessId, processInstanceId));
                        if (ObjectUtil.isNotNull(busForm)) {
                            busForm.setExamineState("finished");
                            //如果业务单是调拨单，那么该单子需要让双方都能发物单位和收物单位的仓管员和审核员都能看见
                            // （前提是发起单据的那一方只有发起人或者经办人和审批人员可见，同级人员不可见）
                            //获取申请人判断是调拨单的哪一方发起的
                            if (busForm.getBussinessType().equals("allocate")) {
                                String agentId = busForm.getAgentId();
                                Long angentOrgId = sysUserOrgService.getOne(new LambdaQueryWrapper<SysUserOrg>()
                                        .eq(SysUserOrg::getUserId, agentId)).getOrgId();
                                Long orgId = (busForm.getStartOrgId() == angentOrgId ? busForm.getEndOrgId() : busForm.getStartOrgId());
                                //将单子信息指定给另一方的仓管员和审核员可见
                                //获取组织机构下的所有仓管员和审核员id
                                String roleList = "(" + JYZBConstant.SH_ROLR_ID + "," + JYZBConstant.GL_ROLR_ID + ")";

                                List<UserListDTO> userList = orgUserMapper.QueryUserByRoleIdAndOrg(roleList, "(" + orgId.toString() + ")");
                                List<String> assigneeList = new ArrayList<>();
                                if (userList.size() > 0)//判断有没有启动的当前单据,并且下一审核人信息不为空,有启动的单据则把审核人信息加入
                                {
                                    for (UserListDTO userId : userList) {
                                        assigneeList.add(userId.getUserID());
                                    }
                                    String assigneeString = String.join(",", assigneeList);
                                    if (ObjectUtil.isNull(busForm.getHistoryAssign())) {
                                        busForm.setHistoryAssign(assigneeString);
                                    } else {
                                        busForm.setHistoryAssign(busForm.getHistoryAssign() + "," + assigneeString);
                                    }
                                }
                            }
                            busFormService.updateById(busForm);
                            //本级报废
                            if (busForm.getBussinessType().equals("remove") && busForm.getRemoveType()==0) {
                                busFormService.updateBrokenResult(busForm);
                            }
                            //如果是上级报废的业务单，需要发送消息通知上级进行确认
                            if (busForm.getBussinessType().equals("remove") && busForm.getRemoveType() == 1){
                                busFormService.sendMsgByRemove(busForm);
                            }
                        }
                    } else if (Type.equals("reassignment")) {//调岗申请单
                        Reassignment one = reassignmentService.getOne(new LambdaQueryWrapper<Reassignment>()
                                .eq(Reassignment::getProcessId, processInstanceId));
                        UpdateReassignmentReq updateReassignmentReq = new UpdateReassignmentReq();
                        one.setExamineState("finished");
                        BeanPlusUtil.copyProperties(one, updateReassignmentReq);
                        //如果同意直接讲警员基础信息进行修改
                        policemanService.changePoliceOrg(updateReassignmentReq);
                        reassignmentService.updateById(one);
                    } else if (Type.equals("stocktakeOrder")) {//盘库申请单

                        String exchangeName = "orderExchange";
                        //需要判断是入库单还是出库单，入库单传收物单位id，出库单传发物单位id
                        BussinessInventory BI = bussinessInventoryService.getOne(new LambdaQueryWrapper<BussinessInventory>()
                                .eq(BussinessInventory::getProcessId, processInstanceId));
                        BI.setExamineState("finished");
                        BI.setApi("BussinessInventory");
                        bussinessInventoryService.updateById(BI);
                        MQ.SendMsg(exchangeName, BI.getOrgId().toString(), BI);
                        OrderName = BI.getOrderNum();
                    } else if (Type.equals("normalOrder")) {
                        OrderMain existOrder = orderMainService.getOne(new LambdaQueryWrapper<OrderMain>()
                                .eq(OrderMain::getProcessId, processInstanceId));
                        existOrder.setExamineState("finished");
                        existOrder.setOrderState("finished");
                        List<OrderDetail> list = orderDetailService.list(new LambdaQueryWrapper<OrderDetail>()
                                .eq(OrderDetail::getOrderId, existOrder.getId()));

                        //通过summaryId将出库记录取出来，并且分类存入orderDetail中
                        LogSummary one = logSummaryService.getOne(new LambdaQueryWrapper<LogSummary>()
                                .eq(LogSummary::getOrderMainId, existOrder.getId()));

                        List<LogDetail> logDetailList = logDetailService.list(new LambdaQueryWrapper<LogDetail>()
                                .eq(LogDetail::getSummaryId, one.getId()));
                        Map<String, DetailJsonReq> map = new HashMap<>();
                        for (LogDetail logDetail : logDetailList) {
                            String key = logDetail.getTypeId() + logDetail.getSizeId() + logDetail.getPrice() + logDetail.getProperty();
                            if (map.containsKey(key)) {
                                DetailJsonReq detailJsonReq = map.get(key);
                                detailJsonReq.setNum(detailJsonReq.getNum() + 1);
                                map.put(key, detailJsonReq);
                            } else {
                                DetailJsonReq detailJsonReq = new DetailJsonReq();
                                detailJsonReq.setNum(1);
                                detailJsonReq.setLocationName(one.getLocationName());
                                detailJsonReq.setLocationId(one.getLocationId());
                                detailJsonReq.setPrice(logDetail.getPrice());
                                detailJsonReq.setProperty(logDetail.getProperty());
                                map.put(key, detailJsonReq);
                            }
                        }
                        for (OrderDetail orderDetail : list) {
                            for (String key : map.keySet()) {
                                if (key.equals(orderDetail.getTypeId() + orderDetail.getSizeId() + orderDetail.getPrice() + orderDetail.getProperty())) {
                                    orderDetail.setDetailJson(JSONObject.toJSONString(map.get(key)));
                                }
                            }
                        }
                        orderMainService.updateById(existOrder);
                        orderDetailService.updateBatchById(list);

                        List<String> collect = logDetailList
                                .stream().map(LogDetail::getInventoryId)
                                .collect(Collectors.toList());

                        if (existOrder.getOrderType().equals("in")) {
                            MQ.SendMsg("orderExchange", existOrder.getEndOrgId().toString(), "NormalToOrder",
                                    0, "NormalToOrder", null, null, collect, null, null);
                        } else {
                            MQ.SendMsg("orderExchange", existOrder.getStartOrgId().toString(), "NormalToOrder",
                                    1, "NormalToOrder", null, null, collect, null, null);
                        }
                    } else if (Type.equals("typeApply")) {
                        ApplyTypeDto applyTypeDto = JSONObject.parseObject(MapUtil.getStr(historicProcessInstance.getProcessVariables(), APPLY_TYPE_INFO), new TypeReference<ApplyTypeDto>() {
                        });
                        EquipmentType type = new EquipmentType();
                        BeanPlusUtil.copyProperties(applyTypeDto, type);
                        EquipmentType parentType = equipmentTypeService.getById(applyTypeDto.getParentId());
                        int newcode = parentType.getMaxCode() + 1;
                        type.setId(String.valueOf(newcode));
                        type.setCode(String.valueOf(newcode));

                        parentType.setMaxCode(newcode);
                        parentType.setCode(String.valueOf(newcode));
                        List<SupplierType> supplierType = new ArrayList<>();
                        //判断req.getSupplierList()是否为空，如果为空则不进行循环
                        if (ObjectUtil.isNotEmpty(applyTypeDto.getSupplierList())) {

                            List<String> list = Arrays.asList(applyTypeDto.getSupplierList().split(","));

                            list.forEach(supply -> {
                                        SupplierType st = new SupplierType();
                                        st.setId(String.valueOf(UUID.randomUUID()));
                                        st.setState(0);
                                        st.setSupplierId(supply);
                                        st.setTypeId(String.valueOf(newcode));
                                        supplierType.add(st);
                                    }
                            );
                            supplierTypeService.saveBatch(supplierType);

                        }

                        equipmentTypeService.updateById(parentType);
                        type.setCreateTime(DateTimeUtil.getCurrentDateTime());
                        type.setUpdateTime(DateTimeUtil.getCurrentDateTime());
                        equipmentTypeService.save(type);
                        MQ.sendToExchange("topicExchange", "org", "InfoChange", 2, "Adding typeInfo");
                        //往es中添加数据
//                        typeRepository.save(type);
                        //创建一个默认号型
                        EquipmentSize size = new EquipmentSize();
                        size.setCode("0");
                        size.setName("无号配号");
                        size.setTypeId(type.getId());
                        size.setCreateTime(DateTimeUtil.getCurrentDateTime());
                        size.setUpdateTime(DateTimeUtil.getCurrentDateTime());
                        equipmentSizeService.save(size);

                    }
                }
                //消息推送
                //如果单子不是自动生成的则进行通知
                OrderMain orderMain = null;
                if (Type.equals("workOrder")){

                    orderMain = orderMainService.getOne(new LambdaQueryWrapper<OrderMain>().eq(OrderMain::getProcessId, processInstanceId));
                    if (ObjectUtil.isNotNull(orderMain) && (ObjectUtil.isEmpty(orderMain.getNote()) || !orderMain.getNote().equals("系统自动生成"))){

                        MessageSendReq sendReq = new MessageSendReq();
                        String startUser = MapUtil.getStr(historicProcessInstance.getProcessVariables(), START_USER_INFO);
                        UserInfo user = JSONObject.parseObject(startUser, UserInfo.class);
                        String Types = MapUtil.getStr(historicProcessInstance.getProcessVariables(), TYPE_ORDER);
                        sendReq.setReceiveUserIds(String.valueOf(user.getUserId()));
                        sendReq.setBizType("pass/" + Types);
                        sendReq.setBizId(Long.valueOf(processInstanceId));
                        sendReq.setMsgTitle("您的申请已通过");
                        sendReq.setMsgContent("您提交的审批【" + mainProcess.getName() + "】已经通过");
                        sendReq.setPriority("0");
                        sendReq.setSendTime(DateTime.now());
                        messageApi.sendMessageNoToken(sendReq);
                    }

                }else {
                    MessageSendReq sendReq = new MessageSendReq();
                    String startUser = MapUtil.getStr(historicProcessInstance.getProcessVariables(), START_USER_INFO);
                    UserInfo user = JSONObject.parseObject(startUser, UserInfo.class);
                    String Types = MapUtil.getStr(historicProcessInstance.getProcessVariables(), TYPE_ORDER);
                    sendReq.setReceiveUserIds(String.valueOf(user.getUserId()));

                    sendReq.setBizType("pass/" + Types);
                    sendReq.setBizId(Long.valueOf(processInstanceId));
                    if (Type.equals("stocktakeOrder"))//整理需要下发的消息
                    {
                        sendReq.setMsgTitle("盘点提醒");
                        sendReq.setMsgContent("盘库单:【" + OrderName + "】已下发");
                    } else {
                        sendReq.setMsgTitle("您的申请已通过");
                        sendReq.setMsgContent("您提交的审批【" + mainProcess.getName() + "】已经通过");
                    }
                    sendReq.setPriority("0");
                    sendReq.setSendTime(DateTime.now());
                    messageApi.sendMessageNoToken(sendReq);
                }
                if (ObjectUtil.isNotNull(orderMain) && ObjectUtil.isNotEmpty(orderMain.getNote()) && orderMain.getNote().equals("系统自动生成")){
                    MessageSendReq sendReq = new MessageSendReq();
                    String startUser = MapUtil.getStr(historicProcessInstance.getProcessVariables(), START_USER_INFO);
                    UserInfo user = JSONObject.parseObject(startUser, UserInfo.class);
                    String Types = MapUtil.getStr(historicProcessInstance.getProcessVariables(), TYPE_ORDER);
                    sendReq.setReceiveUserIds(String.valueOf(user.getUserId()));

                    sendReq.setBizType("pass/" + Types);
                    sendReq.setBizId(Long.valueOf(processInstanceId));
                    if (Type.equals("stocktakeOrder"))//整理需要下发的消息
                    {
                        sendReq.setMsgTitle("盘点提醒");
                        sendReq.setMsgContent("盘库单:【" + OrderName + "】已下发");
                    } else {
                        sendReq.setMsgTitle("您的申请已通过");
                        sendReq.setMsgContent("您提交的审批【" + mainProcess.getName() + "】已经通过");
                    }
                    sendReq.setPriority("0");
                    sendReq.setSendTime(DateTime.now());
                    messageApi.sendMessageNoToken(sendReq);
                }
//            /*推送发送未读数量*/
//            MessageReq req1 = new MessageReq();
//            req1.setReadFlag(0);
//            req1.setReceiveUserId(user.getUserId());
//            Integer count1 = messageApi.queryCount(req1);
//            messageApi.pushMsgToUser(startUser, count1);
            }

        }
    }


}

