package com.junmp.jyzb.listener;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
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.UserListDTO;
import com.junmp.junmpProcess.dto.json.ApproverGroups;
import com.junmp.junmpProcess.dto.json.ChildNode;
import com.junmp.junmpProcess.dto.json.UserInfo;
import com.junmp.junmpProcess.exception.WorkFlowException;
import com.junmp.junmpProcess.mapper.OrgUserMapper;
import com.junmp.jyzb.api.constant.JYZBConstant;
import com.junmp.jyzb.cache.MsgRedisCache;
import com.junmp.jyzb.entity.BusForm;
import com.junmp.jyzb.entity.BussinessInventory;
import com.junmp.jyzb.entity.OrderMain;
import com.junmp.jyzb.entity.Reassignment;
import com.junmp.jyzb.service.BusFormService;
import com.junmp.jyzb.service.BussinessInventoryService;
import com.junmp.jyzb.service.OrderMainService;
import com.junmp.jyzb.service.ReassignmentService;
import com.junmp.v2.auth.api.bean.login.LoginUser;
import com.junmp.v2.auth.api.context.LoginContext;
import com.junmp.v2.message.api.MessageApi;
import com.junmp.v2.message.api.bean.req.MessageSendReq;
import com.junmp.v2.sys.user.service.SysUserOrgService;
import org.flowable.bpmn.model.Process;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.ExecutionListener;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import static com.junmp.junmpProcess.common.CommonConstants.START_USER_INFO;
import static com.junmp.junmpProcess.common.CommonConstants.TYPE_ORDER;
import static com.junmp.junmpProcess.utils.BpmnModelUtils.getChildNode;

/**
 * @author LoveMyOrange
 * @create 2022-10-15 13:35
 */
@Component
public class CounterSignListener implements ExecutionListener {
    @Resource
    public OrderMainService orderMainService;

    @Resource
    public BusFormService busFormService;
    @Resource
    private MessageApi messageApi;
    @Resource
    private RepositoryService repositoryService;
    @Resource
    private OrgUserMapper orgUserMapper;
    @Resource
    private ReassignmentService reassignmentService;

    @Resource
    private SysUserOrgService sysUserOrgService;

    @Resource
    private MsgRedisCache redisCache;

    @Resource
    private BussinessInventoryService bussinessInventoryService;
    @Resource
    private RuntimeService runtimeService;

    @Resource
    protected TaskService taskService;

    @Override
    public void notify(DelegateExecution execution) {
        String currentActivityId = execution.getCurrentActivityId();
        Process mainProcess = repositoryService.getBpmnModel(execution.getProcessDefinitionId()).getMainProcess();
        //获取当前流程的发起人的userId
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(execution.getProcessInstanceId())
                .singleResult();
        //当前流程发起人的userId
        String startUserId = processInstance.getStartUserId();
//        UserTask userTask = (UserTask) mainProcess.getFlowElement(currentActivityId);

        String flowJson = mainProcess.getAttributeValue("http://flowable.org/bpmn", "Junmp");
        JSONObject jsonObject = JSONObject.parseObject(flowJson, new TypeReference<JSONObject>() {
        });
        String processJson = jsonObject.getString("processJson");
        ChildNode childNode = JSONObject.parseObject(processJson, new TypeReference<ChildNode>() {
        });
        List<String> assigneeList = new ArrayList<>();
        String variable = currentActivityId + "assigneeList";
        List usersValue = (List) execution.getVariable(variable);
        List<String> glUserIdList=new ArrayList<>();
        if (usersValue == null) {

            ChildNode currentNode = getChildNode(childNode, currentActivityId);
            if (currentNode == null) {
                throw new WorkFlowException("查找审批人失败,请联系管理员重试");
            }
            ApproverGroups group=currentNode.getApproverGroups().get(0);
            String Type=group.getApproverType();
//            if (Type.equals("1")||Type.equals("8"))//指定人员，不处理
            if (Type.equals("8"))//指定人员，不处理
            {

                List<String> assignedUser = group.getApproverIds();
                for (String userInfo : assignedUser) {
                    assigneeList.add(userInfo);
                }


            }
            else if (Type.equals("5"))//指定角色,查找发起人组织机构下的同角色账号
            {
                List<String> Roles=group.getApproverIds();
                if (Roles.size()>0)//角色不为空
                {
                    //开始拼接传入的多角色
                    String roleList="(";
                    for (String role :Roles)
                    {
                        roleList+=role+",";
                    }

                    roleList = roleList.substring(0, roleList.length() - 1);
                    roleList+=")";//至此拼接完成

                    LoginUser StartUser= LoginContext.getContext().getLoginUser();
                    List<UserListDTO> userList=orgUserMapper.QueryUserByRoleId(roleList, StartUser.getUserId().toString());
                        for (UserListDTO userId :userList)
                        {
                            assigneeList.add(userId.getUserID());
                        }
                if(assigneeList.size()==0)
                {
//                    throw new ServiceException(OrderExceptionEnum.ROLE_ERROR);
                   throw new WorkFlowException("组织机构下无该角色账号，请先添加账号!");
                }

                }


            }
            else if (Type.equals("7"))//指定组织机构中的角色
            {
//                List<UserListDTO> userList=orgUserMapper.QueryUserByRoleIdAndOrg(role);
                List<String> Roles=group.getApproverIds();
                List<String> Orgs=group.getOrgIds();
                if (Roles!=null&&Orgs!=null)//角色不为空,组织机构不为空
                {
                    //开始拼接传入的多角色
                    String roleList="(";
                    for (String role :Roles)
                    {
                        roleList+=role+",";
                    }

                    roleList = roleList.substring(0, roleList.length() - 1);
                    roleList+=")";//至此拼接完成

                    //开始拼接传入的多组织机构
                    String orgList="(";
                    for (String org :Orgs)
                    {
                        orgList+=org+",";
                    }

                    orgList = orgList.substring(0, orgList.length() - 1);
                    orgList+=")";//至此拼接完成

                    List<UserListDTO> userList=orgUserMapper.QueryUserByRoleIdAndOrg(roleList,orgList);
                    for (UserListDTO userId :userList)
                    {
                        assigneeList.add(userId.getUserID());
                    }
                }
                else
                {
                    throw new WorkFlowException("审核流配置不正确，无指定的组织机构！");
                }

            }
            else  if (Type.equals("1"))//上级审批
            {

                LoginUser StartUser= LoginContext.getContext().getLoginUser();
                //查找上级组织机构的userIds(拿的永远是发起人的上一级组织机构)
                List<UserListDTO> userList= orgUserMapper.QueryUserWithParentOrg(startUserId);
                List<String> Roles=group.getApproverIds();
                String roleList="";
                if (Roles.size()>0) { //角色不为空
                    //开始拼接传入的多角色
                    roleList = "(";
                    for (String role : Roles) {
                        roleList += role + ",";
                    }

                    roleList = roleList.substring(0, roleList.length() - 1);
                    roleList += ")";//至此拼接完成
                }else {
                    throw new WorkFlowException("审核流配置不正确，无指定的组织机构！");
                }
                if (userList.size()<=0)//没有上级则本身已是上级
                {
                    //那么我就直接照同级下的满足角色的userId
                    List<UserListDTO> userList1 = orgUserMapper.QueryUserByRoleId(roleList, StartUser.getUserId().toString());
                    for (UserListDTO userId : userList1) {
                        assigneeList.add(userId.getUserID());
                    }

                }else {//取上级的角色进行推送
                    List<UserListDTO> userList1=orgUserMapper.QueryUserByRoleId(roleList, userList.get(0).getUserID());
                    for (UserListDTO userId :userList1)
                    {
                        assigneeList.add(userId.getUserID());
                    }

                    if (Roles.size()==1){
                        String roleId = Roles.get(0);
                        if (roleId.equals(JYZBConstant.SH_ROLR_ID.toString())){
                            glUserIdList = userList.stream()
                                    .filter(userListDTO -> userListDTO.getRoleId().equals(JYZBConstant.GL_ROLR_ID.toString()))
                                    .collect(Collectors.toList())
                                    .stream()
                                    .map(UserListDTO::getUserID)
                                    .collect(Collectors.toList());


                        }

                    }
                }

            }
            else if (Type.equals("10"))//自己审批
            {

                assigneeList.add(LoginContext.getContext().getLoginUser().getUserId().toString());
                execution.setVariable("skip", true);

            }

            String orderType= execution.getVariable("typeOrder").toString();
            if (assigneeList.size()!=0) {
                 execution.setVariable(variable, assigneeList);
                 execution.setVariable("currentAssignee", assigneeList);
                 //为流程进行中的单据设置审核信息
                if (orderType.equals("workOrder"))
                {
                 OrderMain om=   orderMainService.getOne(new LambdaQueryWrapper<OrderMain>()
                            .eq(OrderMain::getProcessId, execution.getProcessInstanceId()));
                 if (om!=null&&assigneeList.size()>0)//判断有没有启动的当前单据,并且下一审核人信息不为空,有启动的单据则把审核人信息加入
                 {

                     String assigneeString = String.join(",", assigneeList);
                     if (ObjectUtil.isNull(om.getHistoryAssign())){
                         om.setHistoryAssign(assigneeString);
                     }else {
                         om.setHistoryAssign(om.getHistoryAssign()+","+assigneeString);
                     }
                     om.setCurrentAssign(assigneeString);
                     orderMainService.updateById(om);
                 }

                }
                else if (orderType.equals("reassignment"))//调岗相关
                {
                    Reassignment re=  reassignmentService.getOne(new LambdaQueryWrapper<Reassignment>()
                            .eq(Reassignment::getProcessId, execution.getProcessInstanceId()));
                    if (re!=null&&assigneeList.size()>0)//判断有没有启动的当前单据,并且下一审核人信息不为空,有启动的单据则把审核人信息加入
                    {

                        String assigneeString = String.join(",", assigneeList);
                        if (ObjectUtil.isNull(re.getHistoryAssign())){
                            re.setHistoryAssign(assigneeString);
                        }else {
                            re.setHistoryAssign(re.getHistoryAssign()+","+assigneeString);
                        }
                        re.setCurrentAssign(assigneeString);
                        reassignmentService.updateById(re);
                    }
                }
                else if (orderType.equals("bussinessOrder"))//业务单据
                {
                    BusForm re=  busFormService.getOne(new LambdaQueryWrapper<BusForm>()
                            .eq(BusForm::getProcessId, execution.getProcessInstanceId()));
                    if (re!=null&&assigneeList.size()>0)//判断有没有启动的当前单据,并且下一审核人信息不为空,有启动的单据则把审核人信息加入
                    {
                        String assigneeString = String.join(",", assigneeList);
                        if (ObjectUtil.isNull(re.getHistoryAssign())){
                            re.setHistoryAssign(assigneeString);
                        }else {
                            re.setHistoryAssign(re.getHistoryAssign()+","+assigneeString);
                        }
                        re.setCurrentAssign(assigneeString);
                        if (CollectionUtil.isNotEmpty(glUserIdList)){
                            re.setHistoryAssign(re.getHistoryAssign()+","+String.join(",",glUserIdList));
                        }
                        busFormService.updateById(re);
                    }
                }
                else if (orderType.equals("stocktakeOrder"))//盘库单据
                {

                    BussinessInventory re = bussinessInventoryService.getOne(new LambdaQueryWrapper<BussinessInventory>()
                            .eq(BussinessInventory::getProcessId, execution.getProcessInstanceId()));
                    if (re!=null&&assigneeList.size()>0)//判断有没有启动的当前单据,并且下一审核人信息不为空,有启动的单据则把审核人信息加入
                    {
                        String assigneeString = String.join(",", assigneeList);
                        if (ObjectUtil.isNull(re.getHistoryAssign())){
                            re.setHistoryAssign(assigneeString);
                        }else {
                            re.setHistoryAssign(re.getHistoryAssign()+","+assigneeString);
                        }
                        re.setCurrentAssign(assigneeString);
                        bussinessInventoryService.updateById(re);
                    }
                }
                 Object skip=execution.getVariable("skip");
                List<MessageSendReq> msgList=new ArrayList<>();
                if (ObjectUtil.isNull(skip)){
                    Optional<String> first = assigneeList.stream().filter(s -> s.equals(startUserId)).findFirst();
                    if (!first.isPresent()){
                        List<MessageSendReq> messageSendReqs = sendMsg(execution, assigneeList, mainProcess);
                        msgList.addAll(messageSendReqs);
                    }else if (orderType.equals("workOrder")){//仅归还入库时消息提醒，业务不做提醒直接审批通过
                        List<MessageSendReq> messageSendReqs = sendMsg(execution, assigneeList, mainProcess);
                        msgList.addAll(messageSendReqs);
                    }
                    if (orderType.equals("typeApply") || Type.equals("1")){
                        if (CollectionUtil.isNotEmpty(msgList)){
                            msgList.forEach(msg->
                                    {
                                        messageApi.sendMessageNoToken(msg);
                                    }
                            );
                        }
                    }
                    redisCache.put(execution.getProcessInstanceId(),JSONObject.toJSONString(msgList));
                    redisCache.put(execution.getProcessInstanceId()+"assigneeList",String.join(",", assigneeList));

                } else {//跳过
                    MessageSendReq sendReq = new MessageSendReq();
                    sendReq.setReceiveUserIds(assigneeList.stream()
                            .distinct()
                            .map(Object::toString)
                            .collect(Collectors.joining(",")));
                    sendReq.setMsgTitle("refresh");
                    sendReq.setMsgContent("消息更新");
                    sendReq.setBizType("1");
                    sendReq.setPriority("1");
                    sendReq.setSendTime(DateTime.now());
                    msgList.add(sendReq);
                    redisCache.put(execution.getProcessInstanceId(),JSONObject.toJSONString(msgList));
                }


             }

        } else {


        }
    }

    public List<MessageSendReq> sendMsg(DelegateExecution execution,List<String> assigneeList,Process mainProcess){
        List<MessageSendReq> msgList=new ArrayList<>();
        List<String> uniqueAssigneeList = assigneeList.stream()
                .distinct()
                .collect(Collectors.toList());
        uniqueAssigneeList.forEach(userId->//为相应的用户推送消息
        {
            if (userId!=LoginContext.getContext().getLoginUser().getUserId().toString())//非本人审核单据
            {
                MessageSendReq sendReq = new MessageSendReq();
                sendReq.setReceiveUserIds(String.valueOf(userId));
                sendReq.setMsgTitle("您有新的待办任务");
                sendReq.setBizType("assign/"+execution.getVariable(TYPE_ORDER).toString());
                sendReq.setBizId(Long.valueOf(execution.getProcessInstanceId()));
                String StartUser=execution.getVariable(START_USER_INFO).toString();
                UserInfo user=  JSONObject.parseObject(StartUser, UserInfo.class);
                sendReq.setMsgContent(user.getRealName()+" 提交的【"+mainProcess.getName()+"】需要您审批，请及时处理");
                sendReq.setPriority("0");
                sendReq.setSendTime(DateTime.now());
                msgList.add(sendReq);

            }

        });
        return msgList;
    }

}
