package com.junmp.jyzb.listener;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
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.*;
import com.junmp.junmpProcess.entity.ProcessTemplates;
import com.junmp.junmpProcess.exception.WorkFlowException;
import com.junmp.junmpProcess.mapper.OrgUserMapper;
import com.junmp.junmpProcess.service.IFlowInstanceService;
import com.junmp.junmpProcess.service.Repository.ProcessTemplateService;
import com.junmp.junmpProcess.vo.TaskDetailVO;
import com.junmp.jyzb.cache.MsgRedisCache;
import com.junmp.jyzb.entity.*;
import com.junmp.jyzb.service.*;
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.bpmn.model.UserTask;
import org.flowable.engine.*;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.ExecutionListener;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;

import static com.junmp.junmpProcess.common.CommonConstants.*;
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
    private StocktakeService stocktakeService;

    @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;

    @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);
        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());
                    }

                }




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

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

            }
            if (assigneeList.size()!=0)
             {
                 execution.setVariable(variable, assigneeList);
                 execution.setVariable("currentAssignee", assigneeList);
                 //为流程进行中的单据设置审核信息
                String orderType= execution.getVariable("typeOrder").toString();
                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);
                        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");
                if (ObjectUtil.isNull(skip)){

                    List<MessageSendReq> msgList=new ArrayList<>();
                    assigneeList.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);
//                            messageApi.sendMessage(sendReq);
//                            messageApi.queryCount(new MessageReq());
                        }

                    });

                    redisCache.put(execution.getProcessInstanceId(),JSONObject.toJSONString(msgList));
                } else {//跳过

                }


             }

        } else {


        }
    }


}
