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

import cn.axzo.foundation.page.PageResp;
import cn.axzo.orggateway.api.nodeuser.OrgNodeUserApi;
import cn.axzo.orggateway.api.nodeuser.dto.OrgNodeUserDTO;
import cn.axzo.orggateway.api.nodeuser.req.ListOrgNodeUserReq;
import cn.axzo.workflow.common.enums.ApproverSpecifyEnum;
import cn.axzo.workflow.common.exception.WorkflowEngineException;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
import cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper;
import com.alibaba.fastjson.JSON;
import groovy.util.logging.Slf4j;
import lombok.AllArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.ListUtils;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.UserTask;
import org.flowable.engine.delegate.DelegateExecution;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static cn.axzo.workflow.common.code.FlowableEngineRespCode.ENGINE_USER_TASK_CALC_ERROR;

/**
 * 基于"固定人员"查询审批人
 *
 * @author wangli
 * @since 2023/11/18 22:56
 */
@Slf4j
@Component
@AllArgsConstructor
public class BasedFixedPersonTaskAssigneeSelector extends AbstractBpmnTaskAssigneeSelector {
    private final OrgNodeUserApi orgNodeUserApi;

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

    @Override
    public List<BpmnTaskDelegateAssigner> select(FlowElement flowElement, DelegateExecution execution,
                                                 Boolean throwException) {
        List<BpmnTaskDelegateAssigner> assigners = new ArrayList<>();
        if (!(flowElement instanceof UserTask)) {
            return super.select(flowElement, execution, throwException);
        }
        BpmnMetaParserHelper.getApproverSpecifyValue((UserTask) flowElement)
                .ifPresent(s -> assigners.addAll(JSON.parseArray(s, BpmnTaskDelegateAssigner.class)));

        Set<Long> workspaceIds = assigners.stream()
                .map(BpmnTaskDelegateAssigner::getTenantId)
                .filter(StringUtils::hasText)
                .map(Long::parseLong)
                .collect(Collectors.toSet());

        List<Long> personIds = assigners.stream()
                .map(BpmnTaskDelegateAssigner::getPersonId)
                .filter(StringUtils::hasText)
                .map(Long::parseLong)
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(personIds)) {
            return Collections.emptyList();
        }
        List<OrgNodeUserDTO> onlineUsers = new ArrayList<>();
        try {
            ListOrgNodeUserReq searchReq = new ListOrgNodeUserReq();
            searchReq.setWorkspaceIds(workspaceIds);
            searchReq.setPersonIds(personIds);
            searchReq.setPage(1);
            searchReq.setPageSize(personIds.size());
            PageResp<OrgNodeUserDTO> pageResp = parseFoundationApiResult(() -> orgNodeUserApi.list(searchReq), "查询指定人员是否在职",
                    "cn.axzo.orggateway.api.nodeuser.OrgNodeUserApi.list", searchReq);
            if (pageResp != null) {
                onlineUsers = pageResp.getData();
            }
        } catch (Exception e) {
            if (Boolean.TRUE.equals(throwException)) {
                throw new WorkflowEngineException(ENGINE_USER_TASK_CALC_ERROR, flowElement.getId(),
                        this.getType(), e.getMessage());
            } else {
                return Collections.emptyList();
            }
        }

        // 只要有在职的人，不会走审批人为空
        if (ListUtils.emptyIfNull(onlineUsers).stream()
                .filter(i -> Objects.equals(i.getIsDelete(), 0L))
                .anyMatch(u -> assigners.stream()
                        .anyMatch(i -> Objects.equals(i.getPersonId(), String.valueOf(u.getPersonId()))
                                && Objects.equals(i.getOuId(), String.valueOf(u.getOrganizationalUnitId()))))) {
            return assigners;
        }

        return Collections.emptyList();
    }

}
