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

import cn.axzo.karma.client.model.request.ListFlowTaskAssignerReq;
import cn.axzo.karma.client.model.response.FlowTaskAssignerResp;
import cn.axzo.workflow.common.enums.ApproverSpecifyEnum;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessDefinitionVO;
import cn.axzo.workflow.common.model.response.category.CategoryItemVO;
import cn.axzo.workflow.core.deletage.approverscope.ApproverScopeDTO;
import cn.axzo.workflow.core.service.BpmnProcessDefinitionService;
import cn.axzo.workflow.core.service.CategoryService;
import cn.hutool.core.collection.CollUtil;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.engine.delegate.DelegateExecution;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

import static cn.axzo.workflow.common.constant.BpmnConstants.BPM_MODEL_CATEGORY;

/**
 * 基于"角色"查询审批人
 *
 * @author wangli
 * @since 2023/11/16 11:37
 */
@Slf4j
@Component
public class BasedRoleTaskAssigneeSelector extends AbstractBpmnTaskAssigneeSelector {

    @Resource
    private CategoryService categoryService;

    @Resource
    private BpmnProcessDefinitionService bpmnProcessDefinitionService;

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

    @Override
    public List<BpmnTaskDelegateAssigner> select(FlowElement flowElement, DelegateExecution execution,
                                                 Boolean throwException) {
        return super.select(flowElement, execution, throwException);
    }

    @Override
    protected List<BpmnTaskDelegateAssigner> invokeService(FlowElement flowElement, DelegateExecution execution,
                                                           ApproverScopeDTO scopeDto) {
        BpmnProcessDefinitionVO processDefinition = bpmnProcessDefinitionService.getProcessDefinition(execution.getProcessDefinitionId());
        Optional<CategoryItemVO> categoryItemVO = categoryService.get(BPM_MODEL_CATEGORY, processDefinition.getKey());
        Map<String, Object> variables = execution.getVariables();
        ListFlowTaskAssignerReq req = ListFlowTaskAssignerReq.builder()
                .procInstId(execution.getProcessInstanceId())
                .procInstType(Integer.valueOf(Objects.requireNonNull(categoryItemVO.map(CategoryItemVO::getWorkspaceTypeCode).orElse(null))))
                .orgScopes(CollectionUtils.isEmpty(scopeDto.getOrgScopes()) ? Collections.emptyList() : scopeDto.getOrgScopes().stream()
                        .map(os -> ListFlowTaskAssignerReq.OrgScope.builder()
                                .ouId(os.getOuId())
                                .nodeId(os.getNodeId())
                                .workspaceId(os.getWorkspaceId())
                                .workspaceType(os.getWorkspaceType())
                                .build())
                        .collect(Collectors.toList()))
                .workerTeamScopes(CollectionUtils.isEmpty(scopeDto.getWorkerTeamScopes()) ? Collections.emptyList() : scopeDto.getWorkerTeamScopes().stream()
                        .map(ot -> ListFlowTaskAssignerReq.OrgScope.builder()
                                .workspaceId(ot.getWorkspaceId())
                                .ouId(ot.getOuId())
                                .nodeId(ot.getNodeId())
                                .workspaceType(ot.getWorkspaceType())
                                .build())
                        .collect(Collectors.toList()))
                .roleIds(super.getTypes(flowElement).stream().map(Long::valueOf).collect(Collectors.toList()))
                .variables(variables)
                .build();

        req.setProcInstId(execution.getProcessInstanceId());
        List<FlowTaskAssignerResp> flowTaskAssigners = parseApiResult(() -> flowSupportApi.listTaskAssignerByRoles(req),
                "审批节点: " + flowElement.getId() + ", 通过角色查询审批人",
                "cn.axzo.karma.client.feign.FlowSupportApi#listTaskAssignerByRoles", req);

        if (CollUtil.isEmpty(flowTaskAssigners)) {
            return super.invokeService(flowElement, execution, scopeDto);
        }
        return flowTaskAssigners.stream()
                .map(u -> BpmnTaskDelegateAssigner.builder()
                        .assignee(String.valueOf(u.getAssignee()))
                        .assigneeType(String.valueOf(u.getAssigneeType()))
                        .tenantId(String.valueOf(u.getTenantId()))
                        .ouId(String.valueOf(u.getOuId()))
                        .personId(String.valueOf(u.getPersonId()))
                        .build())
                .collect(Collectors.toList());
    }

}
