package com.jeeplus.flowable.common.handler;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.jeeplus.extension.domain.FlowAssignee;
import com.jeeplus.extension.domain.TaskDefExtension;
import com.jeeplus.extension.service.TaskDefExtensionService;
import com.jeeplus.extension.service.dto.FlowAssigneeDTO;
import com.jeeplus.sys.domain.User;
import com.jeeplus.sys.service.UserService;
import com.jeeplus.sys.service.dto.UserDTO;
import com.jeeplus.sys.utils.UserUtils;
import org.flowable.bpmn.model.Process;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import java.util.*;

@Component
public class MutiInstanceHandler {

    /**
     * 获得当前节点的处理者列表
     * @param execution 当前执行实例
     * @return 处理者列表
     */
    public List<String> getList(DelegateExecution execution) {
        String taskDefId = execution.getCurrentFlowElement ().getId ();
        Process process = SpringUtil.getBean (RepositoryService.class).getBpmnModel (execution.getProcessDefinitionId ()).getMainProcess ();
        List<TaskDefExtension> list = SpringUtil.getBean (TaskDefExtensionService.class).lambdaQuery ()
                .eq ( TaskDefExtension::getProcessDefId, process.getId () )
                .eq ( TaskDefExtension::getTaskDefId, taskDefId )
                .list ();
        HashSet<String> candidateUserIds = new LinkedHashSet<> ();
        if (list.size () > 0) {
            TaskDefExtension taskDefExtension = list.get (0);
            List<FlowAssigneeDTO> assigneeList = SpringUtil.getBean (TaskDefExtensionService.class).getById (taskDefExtension.getId ()).getFlowAssigneeList ();
            for (FlowAssigneeDTO flowAssignee : assigneeList) {
                switch (flowAssignee.getType ()) {
                    case "user":
                        candidateUserIds.addAll (Arrays.asList (flowAssignee.getValue ().split (",")));
                        break;
                    case "post":
                        if( StrUtil.isNotBlank (flowAssignee.getValue ())){
                            String postId = flowAssignee.getValue ();
                            List<UserDTO> userList = SpringUtil.getBean ( UserService.class).findListByPostId (postId  );
                            candidateUserIds.addAll ( CollectionUtils.extractToList (userList, "id"));
                        }

                        break;
                    case "company":
                        if(StrUtil.isNotBlank (flowAssignee.getValue ())){
                            String companyId = flowAssignee.getValue ();
                            List<User> userList = SpringUtil.getBean (UserService.class).lambdaQuery ().eq ( User::getCompanyId, companyId ).list ();
                            candidateUserIds.addAll (CollectionUtils.extractToList (userList, "id"));
                        }

                        break;
                    case "depart":
                        if(StrUtil.isNotBlank (flowAssignee.getValue ())){
                            String officeId = flowAssignee.getValue ();
                            List<User> userList = SpringUtil.getBean (UserService.class).lambdaQuery ().eq ( User::getOfficeId, officeId ).list ();
                            candidateUserIds.addAll (CollectionUtils.extractToList (userList, "id"));
                        }

                        break;
                    case "role":
                        if(StrUtil.isNotBlank (flowAssignee.getValue ())){
                            String[] roleIds = flowAssignee.getValue ().split (",");
                            for(String roleId: roleIds){
                                List<UserDTO> userList = SpringUtil.getBean (UserService.class).findListByRoleId ( roleId );
                                candidateUserIds.addAll (CollectionUtils.extractToList (userList, "id"));
                            }
                        }
                        break;
                    case "applyUserId":
                        candidateUserIds.add ("${applyUserId}");
                        break;
                    case "previousExecutor":
                        HistoricTaskInstance lastHisTask = SpringUtil.getBean (HistoryService.class).createHistoricTaskInstanceQuery ().processInstanceId (execution.getProcessInstanceId ()).finished ()
                                .includeProcessVariables ().orderByHistoricTaskInstanceEndTime ().desc ().list ().get (0);

                        candidateUserIds.add(lastHisTask.getAssignee ());
                        break;
                    case "currentUserId":
                        candidateUserIds.add( UserUtils.getCurrentUserDTO ().getId ());
                        break;
                    case "sql":
                        Map userMap = SpringUtil.getBean (JdbcTemplate.class).queryForMap (flowAssignee.getValue ());
                        candidateUserIds.add(userMap.get ("id").toString ());
                        break;
                    case "custom":
                        //根据你的自定义标记，请自行实现

                        //如果字符串中包含 "currentUserSql:" 则进行如下代码替换和处理
                        if(flowAssignee.getValue ().contains("currentUserSql:")){
                            //对应sql为：select su.* from sys_user_role a left join sys_role sr on sr.id = a.role_id left join sys_user su on su.id = a.user_id left join sys_office so on so.id = su.office_id where sr.en_name= 'bmzr' and so.id = (select office_id from sys_user where id = @currentUser.id)
                            //用于查询当前登录人的部门主任人员信息
                            UserDTO currentUserDTO = UserUtils.getCurrentUserDTO();
                            String sql = flowAssignee.getValue ();
                            if(sql.contains("@currentUser.id")){
                                //将标志进行去除
                                sql = sql.replaceAll("currentUserSql:","");
                                //将判断条件进行替换
                                sql = sql.replaceAll("@currentUser.id","'" + currentUserDTO.getId() + "'");
                            }
                            List<Map<String, Object>> maps = SpringUtil.getBean(JdbcTemplate.class).queryForList(sql);
                            for (Map<String, Object> map : maps) {
                                candidateUserIds.add(map.get ("id").toString ());
                            }
                        }
                        //如果字符串中包含 "cwCurrentUserSql:" 则进行如下代码替换和处理
                        if(flowAssignee.getValue ().contains("cwCurrentUserSql:")){
                            //对应sql为：select su.* from sys_user_role a left join sys_role sr on sr.id = a.role_id left join sys_user su on su.id = a.user_id left join sys_office so on so.id = su.office_id where sr.en_name= 'bmzr' and so.id = (select office_id from sys_user where id = @currentUser.id)
                            //用于查询当前登录人的部门主任人员信息
                            UserDTO currentUserDTO = UserUtils.getCurrentUserDTO();
                            String sql = flowAssignee.getValue ();
                            if(sql.contains("@currentUser.id")){
                                //将标志进行去除
                                sql = sql.replaceAll("cwCurrentUserSql:","");
                                //将判断条件进行替换
                                sql = sql.replaceAll("@currentUser.id","'" + currentUserDTO.getId() + "'");
                            }
                            if(sql.contains("@currentUser.officeDTO.name")){
                                //将标志进行去除
                                sql = sql.replaceAll("cwCurrentUserSql:","");
                                //将判断条件进行替换
                                sql = sql.replaceAll("@currentUser.officeDTO.name","'" + currentUserDTO.getOfficeDTO().getName() + "'");
                            }
                            List<Map<String, Object>> maps = SpringUtil.getBean(JdbcTemplate.class).queryForList(sql);
                            for (Map<String, Object> map : maps) {
                                candidateUserIds.add(map.get ("id").toString ());
                            }
                        }
                        //如果字符串中包含 "zsCurrentUserSql:" 则进行如下代码替换和处理
                        if(flowAssignee.getValue ().contains("zsbxCurrentUserSql:")){
                            //对应sql为：select su.* from sys_user_role a left join sys_role sr on sr.id = a.role_id left join sys_user su on su.id = a.user_id left join sys_office so on so.id = su.office_id where sr.en_name= 'bmzr' and so.id = (select office_id from sys_user where id = @currentUser.id)
                            //用于查询当前登录人的部门主任人员信息
                            UserDTO currentUserDTO = UserUtils.getCurrentUserDTO();
                            String sql = flowAssignee.getValue ();
                            if(sql.contains("@currentUser.id")){
                                //将标志进行去除
                                sql = sql.replaceAll("zsbxCurrentUserSql:","");
                                //将判断条件进行替换
                                sql = sql.replaceAll("@currentUser.id","'" + currentUserDTO.getId() + "'");
                            }
                            if(sql.contains("@currentUser.officeDTO.name")){
                                //将标志进行去除
                                sql = sql.replaceAll("zsbxCurrentUserSql:","");
                                //将判断条件进行替换
                                sql = sql.replaceAll("@currentUser.officeDTO.name","'" + currentUserDTO.getOfficeDTO().getName() + "'");
                            }
                            List<Map<String, Object>> maps = SpringUtil.getBean(JdbcTemplate.class).queryForList(sql);
                            for (Map<String, Object> map : maps) {
                                candidateUserIds.add(map.get ("id").toString ());
                            }
                        }
                        break;
                }
            }
        }

        return new ArrayList<> (candidateUserIds);

    }

    /**
     * 获取会签是否结束
     * @param execution 当前执行实例
     * @return 是否结束
     */
    public boolean getComplete(DelegateExecution execution) {
        Integer nrOfCompletedInstances = (Integer) execution.getVariable("nrOfCompletedInstances");
        Integer nrOfInstances = (Integer) execution.getVariable("nrOfInstances");
        int agreeCount = 0, rejectCount = 0, abstainCount = 0;
        Map<String, Object> vars = execution.getVariables();
        for (String key : vars.keySet()) {
            //会签投票以SIGN_VOTE+TaskId标识
            //获得会签投票的统计结果
//            if (key.contains(FlowConst.SIGN_VOTE) && !key.equals(FlowConst.SIGN_VOTE_RESULT)) {
//                Integer value = (Integer) vars.get(key);
//                //统计同意、驳回、弃权票数
//                //省略代码若干......
//            }
        }
        //以下为一段简单的规则，可以按情况实现自己的会签规则
        if (!nrOfCompletedInstances.equals(nrOfInstances)) {
            //必须等所有的办理人都投票
            return false;
        } else {
            //会签全部完成时,使用默认规则结束
            if (rejectCount > 0) {
                //有反对票，则最终的会签结果为不通过
                //移除SIGN_VOTE+TaskId为标识的参数
//                removeSignVars(execution);
                //增加会签结果参数，以便之后流转使用
//                execution.setVariable(FlowConst.SIGN_VOTE_RESULT, false);
                //会签结束
                return true;
            } else {
                //没有反对票时，则最终的会签结果为通过
//                removeSignVars(execution);
//                execution.setVariable(FlowConst.SIGN_VOTE_RESULT, true);
                return true;
            }
        }
    }





}
