package cn.axzo.workflow.server.controller.delegate;

import cn.axzo.orggateway.api.nodeuser.OrgNodeUserApi;
import cn.axzo.orggateway.api.nodeuser.dto.FlowTaskAssignerScopeDTO;
import cn.axzo.orggateway.api.nodeuser.enums.FlowTaskAssignerQuerySceneEnum;
import cn.axzo.orggateway.api.nodeuser.req.FlowTaskAssignerV2Req;
import cn.axzo.orggateway.api.nodeuser.resp.FlowTaskAssignerV2Resp;
import cn.axzo.workflow.common.enums.ApproverSpecifyEnum;
import cn.axzo.workflow.common.enums.SignApproverOrgLimitEnum;
import cn.axzo.workflow.common.model.dto.CooperationOrgDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.ListUtils;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.engine.delegate.DelegateExecution;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

import static cn.axzo.workflow.common.constant.BpmnConstants.BIZ_ORG_RELATION;
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_INITIATOR;
import static cn.axzo.workflow.common.enums.ApproverEmptyHandleTypeEnum.transferToAdmin;
import static cn.axzo.workflow.common.enums.ApproverSpecifyRangeUnitEnum.in_project;
import static cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper.getApproverEmptyHandleType;
import static cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper.getAreaFilterEnable;
import static cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper.getInitiatorLeaderRangeUnit;
import static cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper.getSpecialtyFilterEnable;

/**
 * 基于"发起人主管"查询审批人
 *
 * @author wangli
 * @since 2023/11/16 11:41
 */
@Slf4j
@Component
public class BasedInitiatorLeaderV2TaskAssigneeSelector extends AbstractBpmnTaskAssigneeSelector {

    @Resource
    private OrgNodeUserApi orgNodeUserApi;

    @Override
    public String getType() {
        return ApproverSpecifyEnum.initiatorLeader_v2.getType();
    }

    @Override
    public List<BpmnTaskDelegateAssigner> select(FlowElement flowElement, DelegateExecution execution,
                                                 Boolean throwException) {
        // 获取发起人
        BpmnTaskDelegateAssigner initiator =
                BpmnTaskDelegateAssigner.toObjectCompatible(execution.getVariables().get(INTERNAL_INITIATOR));
        if (Objects.isNull(initiator)) {
            return Collections.emptyList();
        }

        CooperationOrgDTO orgDTO = (CooperationOrgDTO) execution.getVariables().get(BIZ_ORG_RELATION);
        FlowTaskAssignerV2Req.FlowTaskAssignerV2ReqBuilder v2ReqBuilder = FlowTaskAssignerV2Req.builder()
                .scene(FlowTaskAssignerQuerySceneEnum.BY_INITIATOR_MANAGER)
                .scope(FlowTaskAssignerScopeDTO.builder()
                        .nodeId(initiator.parseNodeId())
                        .upLevel(SignApproverOrgLimitEnum.LV_0.getCode())
                        .crossDomain(getInitiatorLeaderRangeUnit(flowElement).filter(unit -> unit != in_project).isPresent())
                        .build())
                .initiatorPersonId(initiator.parsePersonId())
                .areaCodes(getAreaFilterEnable(flowElement) ? Sets.newHashSet(ListUtils.emptyIfNull(orgDTO.getIncludeAreaCodes())) : Sets.newHashSet())
                .specialtyCodes(getSpecialtyFilterEnable(flowElement) ? Sets.newHashSet(ListUtils.emptyIfNull(orgDTO.getIncludeSpecialtyCodes())) : Sets.newHashSet())
                .querySupervisorWhileMissMatched(getApproverEmptyHandleType(flowElement).filter(type -> Objects.equals(type, transferToAdmin)).isPresent());

        FlowTaskAssignerV2Req request = v2ReqBuilder.build();
        List<FlowTaskAssignerV2Resp> apiResultUsers = parseFoundationApiResult(() -> orgNodeUserApi.listFlowTaskAssignerV2(request), "新版查询发起人主管的审批人" + execution.getProcessInstanceId() + flowElement.getId(),
                "cn.axzo.orggateway.api.nodeuser.OrgNodeUserApi.listFlowTaskAssignerV2", request);
        return convertApprover(apiResultUsers);
    }

}
