package cn.stylefeng.workflow.instance.modular.task.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.stylefeng.workflow.api.entity.design.Definition;
import cn.stylefeng.workflow.api.entity.instance.RuntimeInstance;
import cn.stylefeng.workflow.api.pojo.InstanceContext;
import cn.stylefeng.workflow.api.pojo.InstanceVariable;
import cn.stylefeng.workflow.api.pojo.config.node.approver.ApproverConfig;
import cn.stylefeng.workflow.instance.core.condition.*;
import cn.stylefeng.workflow.instance.core.condition.base.BaseApproverRule;
import cn.stylefeng.workflow.instance.modular.task.service.RuApproverService;
import cn.stylefeng.workflow.rule.api.RuleEngineApi;
import cn.stylefeng.workflow.rule.api.condition.BaseRule;
import cn.stylefeng.workflow.rule.api.condition.BaseWorkflowRule;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class RuApproverServiceImpl implements RuApproverService {

    @Resource
    private RuleEngineApi ruleEngineApi;

    @Override
    public Set<Long> getNodeApproverResult(ApproverConfig approverConfig, InstanceContext instanceContext) {

        ArrayList<BaseRule<List<Long>>> conditionList = new ArrayList<>();

        conditionList.add(new PersonApproverRule());

        conditionList.add(new PositionApproverRule());


        conditionList.add(new DeptPolicyApproverRule());

        conditionList.add(new RoleApproverRule());

        conditionList.add(new FormApproverRule());

        conditionList.add(new CustomApproverRule());

        conditionList.add(new SubmitterApproverRule());

        conditionList.add(new VariableApproverRule());

        HashMap<String, Object> ruleConditions = new HashMap<>();
        ruleConditions.put(BaseWorkflowRule.DECISION_FACTS_INSTANCE_CONTEXT, instanceContext);
        ruleConditions.put(BaseApproverRule.DECISION_FACTS_NODE_APPROVER, approverConfig);

        ruleEngineApi.calcResult(conditionList, ruleConditions);

        Set<Long> finalUserIdList = new LinkedHashSet<>();
        for (BaseRule<List<Long>> listBaseRule : conditionList) {
            if (ObjectUtil.isNotEmpty(listBaseRule.getResult())) {
                finalUserIdList.addAll(listBaseRule.getResult());
            }
        }
        return finalUserIdList;
    }

    @Override
    public Set<Long> customGetNodeApproverResult(ApproverConfig approverConfig, Long applicantOrgId, Definition flowDefinition,
                                                 InstanceVariable instanceVariable) {

        InstanceContext instanceContext = new InstanceContext();

        RuntimeInstance runtimeInstance = new RuntimeInstance();
        runtimeInstance.setApplicantOrgId(applicantOrgId);
        instanceContext.setRuntimeInstance(runtimeInstance);

        instanceContext.setDefinition(flowDefinition);

        instanceContext.setInstanceVariable(instanceVariable);

        return this.getNodeApproverResult(approverConfig, instanceContext);
    }

}
