package com.chinaweal.aiccs.aiccs.business.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chinaweal.aiccs.aiccs.business.entity.XrActivity;
import com.chinaweal.aiccs.aiccs.business.entity.XrOpinion;
import com.chinaweal.aiccs.aiccs.business.entity.XrTaskList;
import com.chinaweal.aiccs.aiccs.business.mapper.XrActivityMapper;
import com.chinaweal.aiccs.aiccs.business.rules.init.FlowUtil;
import com.chinaweal.aiccs.aiccs.business.rules.init.InitRules;
import com.chinaweal.aiccs.aiccs.business.rules.model.NodeModel;
import com.chinaweal.aiccs.aiccs.business.rules.model.RuleModel;
import com.chinaweal.aiccs.aiccs.business.rules.model.SequenceFlowModel;
import com.chinaweal.aiccs.aiccs.business.service.IXrActivityService;
import com.chinaweal.aiccs.aiccs.business.service.IXrOpinionService;
import com.chinaweal.aiccs.aiccs.business.service.IXrTaskListService;
import com.chinaweal.aiccs.common.constant.FlowConstant;
import com.chinaweal.aicorg.model.AICUser;
import com.chinaweal.aicorg.pojo.AICPermission;
import com.chinaweal.youfool.framework.springboot.exception.custom.BusinessException;
import com.chinaweal.youfool.framework.sso.util.SSOUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author quebh
 * @since 2023-05-04
 */
@Service
@Slf4j
public class XrActivityServiceImpl extends ServiceImpl<XrActivityMapper, XrActivity> implements IXrActivityService {

    @Resource
    @Lazy
    private IXrTaskListService iXrTaskListService;
    @Resource
    private IXrOpinionService iXrOpinionService;

    /**
     * 流程规则校验
     *
     * @param definedName
     * @param fromNodeID
     * @param nextNodeID
     * @return
     * @author ymc
     * @since 2024年3月7日 11:42
     */
    private static void checkXMLRule(String definedName, String fromNodeID, String nextNodeID) {
        if (fromNodeID == null) {
            throw new BusinessException("开始节点为空，请检查。");
        }
        if (nextNodeID == null) {
            throw new BusinessException("下一节点为空，请检查。");
        }
        RuleModel ruleModel = InitRules.getRuleModels().get(definedName);
        if (ruleModel == null) {
            throw new BusinessException("找不到规则定义" + definedName + "，请检查。");
        }
        Map<String, NodeModel> nodeModelMap = ruleModel.getNodeModelMap();
        NodeModel fromNode = nodeModelMap.get(fromNodeID);
        if (fromNode == null) {
            throw new BusinessException("开始节点" + fromNodeID + "不存在，请检查。");
        }
        NodeModel toNode = nodeModelMap.get(nextNodeID);
        if (toNode == null) {
            throw new BusinessException("下一节点" + nextNodeID + "不存在，请检查。");
        }
        Map<String, SequenceFlowModel> sequenceFlowModelMap = ruleModel.getSequenceFlowModelMap();
        if (sequenceFlowModelMap.get(fromNodeID + "_" + nextNodeID) == null) {
            throw new BusinessException(fromNodeID + "_" + nextNodeID + "流程线不存在，请检查。");
        }
    }

    @Override
    public String startWorkFlow(XrTaskList taskListModel, AICUser user, String definitionName) {
        //工作流规则
        RuleModel ruleModel = InitRules.getRuleModels().get(definitionName);
        if (ruleModel == null) {
            throw new BusinessException(definitionName + "不存在于流程模版中，请检查！");
        }

        // linkName
        String linkType = ruleModel.getStartnodeid();

//        taskListModel.setAcceptNo(user.getRegionID().substring(0, 6) + uuidUtil.getCurAcceptNo());
        //因xr_id_maker容易被锁，临时用新的生成规则生成受理编号
        LocalDateTime now = LocalDateTime.now();  // 获取当前日期和时间
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");  // 定义格式化模式
        String formattedDate = now.format(formatter);  // 将日期格式化为字符串
        taskListModel.setAcceptNo("7"+ formattedDate + UUID.randomUUID().toString().replaceAll("-", "").substring(0, 8));

        XrActivity xrActivity = new XrActivity();
        xrActivity.setActivityId(UUID.randomUUID().toString());
        xrActivity.setTaskId(taskListModel.getTaskLikeId());
        xrActivity.setLinkStatus(FlowConstant.LINK_STATUS_ONE);
        xrActivity.setLinkType(ruleModel.getStartnodeid());
        xrActivity.setLinkName(null);
        xrActivity.setUserId(user.getPrimaryKey());
        xrActivity.setDepId(user.getRegionID());
        xrActivity.setStatus("0");
        xrActivity.setOpenName(user.getName());
        xrActivity.setOpenId(user.getPrimaryKey());
        save(xrActivity);

        taskListModel.setWorkFlowId(xrActivity.getActivityId());
        taskListModel.setLinkName(null);
        iXrTaskListService.updateById(taskListModel);
        return xrActivity.getActivityId();
    }

    @Override
    public String processWork(String taskLikeId, String nextNodeID, String[] nextPerformerIds, AICUser user) {
        LambdaQueryWrapper<XrActivity> xrActivityQueryWrapper = new LambdaQueryWrapper<>();
        xrActivityQueryWrapper.eq(XrActivity::getTaskId, taskLikeId)
                .eq(XrActivity::getLinkStatus, "1");
        List<XrActivity> list = list(xrActivityQueryWrapper);

        for (XrActivity xrActivity : list) {
            xrActivity.setLinkStatus("0");
            xrActivity.setOpenName(user.getName());
            xrActivity.setOpenId(user.getPrimaryKey());
            updateById(xrActivity);
        }
        if ("clueReturn".equals(nextNodeID)) {
            XrActivity xrActivity1 = list.get(0);
            XrActivity xrActivity = new XrActivity();
            xrActivity.setActivityId(UUID.randomUUID().toString());
            xrActivity.setTaskId(taskLikeId);
            if (StringUtils.equals(FlowConstant.LINK_TYPE_EXAMINE, xrActivity1.getLinkType())) {
//                xrActivity.setLinkName(FlowConstant.LINK_TYPE_MAP.get(FlowConstant.LINK_TYPE_HANDLE));
                xrActivity.setLinkType(FlowConstant.LINK_TYPE_HANDLE);
                nextNodeID = FlowConstant.LINK_TYPE_HANDLE;
            } else if (StringUtils.equals(FlowConstant.LINK_TYPE_APPROVE, xrActivity1.getLinkType())) {
//                xrActivity.setLinkName(FlowConstant.LINK_TYPE_MAP.get(FlowConstant.LINK_TYPE_EXAMINE));
                xrActivity.setLinkType(FlowConstant.LINK_TYPE_EXAMINE);
                nextNodeID = FlowConstant.LINK_TYPE_EXAMINE;
            }
            xrActivity.setLinkType(nextNodeID);
            xrActivity.setLinkStatus("1");
//            xrActivity.setLinkName(FlowConstant.LINK_TYPE_MAP.get(nextNodeID));
            xrActivity.setUserId(list.get(0).getOpenId());
            xrActivity.setDepId(user.getRegionID());
            xrActivity.setStatus("0");
            xrActivity.setOpenName(user.getName());
            xrActivity.setOpenId(user.getPrimaryKey());
            save(xrActivity);
            if (nextPerformerIds.length != 0) {
                nextPerformerIds[0] = list.get(0).getOpenId();
            }
        } else {
            if (nextPerformerIds == null) {
                XrActivity xrActivity = new XrActivity();
                xrActivity.setActivityId(UUID.randomUUID().toString());
                xrActivity.setTaskId(taskLikeId);
                xrActivity.setLinkType(nextNodeID);
                xrActivity.setLinkStatus("1");
//                xrActivity.setLinkName(FlowConstant.LINK_TYPE_MAP.get(nextNodeID));
                xrActivity.setUserId(user.getPrimaryKey());
                xrActivity.setDepId(user.getRegionID());
                xrActivity.setStatus("0");
                xrActivity.setOpenName(user.getName());
                xrActivity.setOpenId(user.getPrimaryKey());
                save(xrActivity);
            } else {
                for (String nextPerformerId : nextPerformerIds) {
                    XrActivity xrActivity = new XrActivity();
                    xrActivity.setActivityId(UUID.randomUUID().toString());
                    xrActivity.setTaskId(taskLikeId);
                    xrActivity.setLinkType(nextNodeID);
                    xrActivity.setLinkStatus("1");
//                    xrActivity.setLinkName(FlowConstant.LINK_TYPE_MAP.get(nextNodeID));
                    xrActivity.setUserId(nextPerformerId);
                    xrActivity.setDepId(user.getRegionID());
                    xrActivity.setStatus("0");
                    xrActivity.setOpenName(user.getName());
                    xrActivity.setOpenId(user.getPrimaryKey());
                    save(xrActivity);
                }
            }

        }
        return nextNodeID;
    }

    @Override
    public String startWorkFlowByTemplate(XrTaskList taskListModel, List<AICUser> userList, String ident) {
        //工作流规则
        String definitionName = taskListModel.getWorkFlowId();
        RuleModel ruleModel = InitRules.getRuleModels().get(definitionName);
        if (ruleModel == null) {
            throw new BusinessException(definitionName + "不存在于流程模版中，请检查！");
        }
        log.info("开启{}-{}流程", ruleModel.getDefinedname(), ruleModel.getDescription());

        String linkType = ruleModel.getStartnodeid();

        if (StringUtils.isNotBlank(ident)) {
            XrActivity xrActivity = new XrActivity();
            xrActivity.setDepId(taskListModel.getApplyOrgId())
                    .setTaskId(taskListModel.getTaskLikeId())
                    .setLinkType(linkType)
                    .setLinkStatus("1")
                    .setLinkName(FlowUtil.getLinkTypeName(definitionName, linkType))
                    .setStatus("0")
                    .setIdent(ident);
            save(xrActivity);
        } else {
            for (AICUser nextUser : userList) {
                XrActivity xrActivity = new XrActivity();
                xrActivity.setUserId(nextUser.getPrimaryKey())
                        .setDepId(nextUser.getRegionID())
                        .setTaskId(taskListModel.getTaskLikeId())
                        .setLinkType(linkType)
                        .setLinkStatus("1")
                        .setLinkName(FlowUtil.getLinkTypeName(definitionName, linkType))
                        .setStatus("0")
                        .setIdent(nextUser.getPrimaryKey());
                save(xrActivity);
            }
        }
        taskListModel.setLinkName(FlowUtil.getLinkTypeName(definitionName, linkType));
        return FlowUtil.getLinkTypeName(definitionName, linkType);
    }

    @Override
    public String processWorkByTemplate(XrTaskList taskListModel, List<AICUser> userList, String nextNodeID, XrOpinion opinion, String ident) {
        AICUser user = SSOUtil.getUser();
        String activityId = null;

        // 流程规则校验
        NodeModel currentNodeModel = findCurrentNode(taskListModel.getTaskLikeId());
        checkXMLRule(taskListModel.getWorkFlowId(), currentNodeModel.getId(), nextNodeID);

        // 获取当前环节信息
        List<XrActivity> activityList = list( new LambdaQueryWrapper<XrActivity>().eq(XrActivity::getTaskId, taskListModel.getTaskLikeId())
                .eq(XrActivity::getLinkStatus, "1"));
        if (CollUtil.isEmpty(activityList))
            throw new BusinessException("流程节点为空，taskId：" + taskListModel.getTaskLikeId());

        // 处理当前环节信息
        if (activityList.size() == 1) {
            XrActivity xrActivity = activityList.get(0);
            activityId = xrActivity.getActivityId();
            xrActivity.setLinkStatus("0");
            xrActivity.setOpenName(user.getName());
            xrActivity.setOpenId(user.getPrimaryKey());
            updateById(xrActivity);
        } else {
            Set<String> delIds = new HashSet<>();
            for (XrActivity xrActivity : activityList) {
                if (user.getPrimaryKey().equals(xrActivity.getUserId())) {
                    activityId = xrActivity.getActivityId();
                    xrActivity.setLinkStatus("0");
                    xrActivity.setOpenName(user.getName());
                    xrActivity.setOpenId(user.getPrimaryKey());
                    updateById(xrActivity);
                } else {
                    delIds.add(xrActivity.getActivityId());
                }
                if (!delIds.isEmpty()) this.removeByIds(delIds);
            }
        }

        // 添加下一环节信息
        RuleModel ruleModel = InitRules.getRuleModels().get(taskListModel.getWorkFlowId());
        NodeModel nodeModel = ruleModel.getNodeModelMap().get(nextNodeID);
        if (nodeModel.isEnd()) {
            XrActivity nextActivity = new XrActivity();
            nextActivity.setUserId(user.getPrimaryKey())
                    .setDepId(user.getRegionID())
                    .setOpenName(user.getName())
                    .setOpenId(user.getPrimaryKey())
                    .setTaskId(taskListModel.getTaskLikeId())
                    .setLinkType(nodeModel.getId())
                    .setLinkStatus("1")
                    .setLinkName(nodeModel.getDescription())
                    .setStatus("0")
                    .setIdent(user.getPrimaryKey());
            save(nextActivity);
        } else {
            if (StringUtils.isNotBlank(ident)) {
                XrActivity nextActivity = new XrActivity();
                nextActivity.setDepId(taskListModel.getApplyOrgId())
                        .setTaskId(taskListModel.getTaskLikeId())
                        .setLinkType(nodeModel.getId())
                        .setLinkStatus("1")
                        .setLinkName(nodeModel.getDescription())
                        .setStatus("0")
                        .setIdent(ident);
                save(nextActivity);
            } else {
                for (AICUser nextUser : userList) {
                    XrActivity nextActivity = new XrActivity();
                    nextActivity.setUserId(nextUser.getPrimaryKey())
                            .setDepId(nextUser.getRegionID())
                            .setTaskId(taskListModel.getTaskLikeId())
                            .setLinkType(nodeModel.getId())
                            .setLinkStatus("1")
                            .setLinkName(nodeModel.getDescription())
                            .setStatus("0")
                            .setIdent(nextUser.getPrimaryKey());
                    save(nextActivity);
                }
            }
        }

        if (opinion != null) iXrOpinionService.save(opinion.setActivityId(activityId));
        return nodeModel.getDescription();
    }

    @Override
    public List<SequenceFlowModel> findNextSequenceFlowList(String taskId) {
        XrTaskList xrTaskList = iXrTaskListService.getById(taskId);
        LambdaQueryWrapper<XrActivity> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(XrActivity::getTaskId, taskId)
                .eq(XrActivity::getLinkStatus, "1");
        XrActivity xrActivity = getOne(queryWrapper, false);
        String linkType = xrActivity.getLinkType();
        List<SequenceFlowModel> nextSequenceFlowList = null;
        RuleModel ruleModel = InitRules.getRuleModels().get(xrTaskList.getWorkFlowId());
        if (!ruleModel.getEndnodeids().contains(linkType)) {
            nextSequenceFlowList = new ArrayList<>();
            NodeModel nodeModel = ruleModel.getNodeModelMap().get(linkType);
            for (SequenceFlowModel sequenceFlowModel : ruleModel.getSequenceFlowModelMap().values()) {
                String[] ids = StringUtils.split(sequenceFlowModel.getId(), "_");
                if (StringUtils.equals(ids[0], nodeModel.getId())) {
                    nextSequenceFlowList.add(sequenceFlowModel);
                }
            }
        }
        return nextSequenceFlowList;
    }

    @Override
    public NodeModel findCurrentNode(String taskId) {
        XrTaskList taskListModel = iXrTaskListService.getById(taskId);
        LambdaQueryWrapper<XrActivity> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(XrActivity::getTaskId, taskId)
                .eq(XrActivity::getLinkStatus, "1");
        XrActivity xrActivity = getOne(queryWrapper, false);
        String linkType = xrActivity.getLinkType();
        RuleModel ruleModel = InitRules.getRuleModels().get(taskListModel.getWorkFlowId());
        return ruleModel.getNodeModelMap().get(linkType);
    }

    @Override
    public XrActivity findOperator(String taskId, String linkType) {
        LambdaQueryWrapper<XrActivity> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(XrActivity::getTaskId, taskId)
                .eq(XrActivity::getLinkStatus, "0")
                .eq(XrActivity::getLinkType, linkType)
                .orderByAsc(XrActivity::getCreateTime);
        return getOne(queryWrapper, false);
    }

    @Override
    public boolean checkPermissionsAndNodeID(Map<String, AICPermission> aicPermissions, String currentNodeID,String nextNodeID,String inWorkFlow) {
        //需要排除判断的环节
        Set<String> nextNodeIDs = new HashSet<>();
        nextNodeIDs.add("nullify");  //作废
        nextNodeIDs.add("replenish");    //补正材料
        nextNodeIDs.add("transfer");    //转办
        if(StringUtils.equals(inWorkFlow,"abnormal")){
            nextNodeIDs.add("examine");  //审核
        } else if(StringUtils.equals(inWorkFlow,"seriousillegal")){
            nextNodeIDs.add("law");  //执法
        }
        //根据下一环节判断需要排除判断的环节
        if (nextNodeIDs.contains(nextNodeID)) {
            //若需要排除判断的环节，直接返回true
            return true;
        }

        //针对当前环节是回退的，进行特殊处理
        if (currentNodeID.contains("Return")) {
            currentNodeID = currentNodeID.replace("Return", "");
        }

        // 将首字母改为大写
        currentNodeID = currentNodeID.substring(0, 1).toUpperCase() + currentNodeID.substring(1);
        //将节点改为权限名
        currentNodeID = "xr" + currentNodeID;
        //判断当前环节是否有权限
        return aicPermissions.containsKey(currentNodeID);
    }
}
