package cn.axzo.workflow.core.deletage;

import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
import cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper;
import cn.axzo.workflow.core.deletage.approverscope.ApproverScopeDTO;
import cn.axzo.workflow.core.deletage.approverscope.ApproverScopeProcesssor;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.http.HttpStatus;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.UserTask;
import org.flowable.engine.delegate.DelegateExecution;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.stream.Collectors;

/**
 * 抽象的流程任务审批人选择器
 *
 * @author wangli
 * @since 2023/11/17 11:35
 */
@Slf4j
public abstract class AbstractBpmnTaskAssigneeSelector implements BpmnTaskAssigneeSelector, ApplicationContextAware {
    private ApplicationContext applicationContext;

    @Override
    public List<BpmnTaskDelegateAssigner> select(UserTask userTask, DelegateExecution execution) {
        return (List<BpmnTaskDelegateAssigner>) BpmnMetaParserHelper.getApproverScope(userTask)
                .map(approverScopeEnum -> {
                    if (Objects.isNull(approverScopeEnum.getProcessor())) {
                        return Collections.emptyList();
                    } else {
                        ApproverScopeProcesssor processor =
                                applicationContext.getBean(approverScopeEnum.getProcessor(),
                                        ApproverScopeProcesssor.class);
                        ApproverScopeDTO scopeDto = processor.select(userTask, execution);
                        if (CollUtil.isEmpty(scopeDto.getOrgScopes())) {
                            log.info("roleTaskAssignee no get orgScopes");
                            return Collections.emptyList();
                        }
                        return invokeService(userTask, execution, scopeDto);
                    }
                }).orElseGet(Collections::emptyList);
    }

    protected List<BpmnTaskDelegateAssigner> invokeService(UserTask userTask, DelegateExecution execution,
                                                           ApproverScopeDTO scopeDto) {
        return Collections.emptyList();
    }

    protected final <T> T parseApiResult(Supplier<ApiResult<T>> supplier, String operatorDesc, Object... param) {
        log.info(operatorDesc + "-Param: " + JSONUtil.toJsonStr(param));
        ApiResult<T> result = supplier.get();
        log.info(operatorDesc + "-Result: " + JSONUtil.toJsonStr(result));
        Assert.notNull(result, "服务调用异常");
        // 200自定义处理
        if (HttpStatus.HTTP_OK != result.getCode()) {
            throw new WorkflowEngineException(result.getMsg());
        }
        return result.getData();
    }

    @Override
    public List<String> getTypes(UserTask userTask) {
        // 默认解析格式：[{"name":"预算员", "value":"xxxx"}]
        return BpmnMetaParserHelper.getApproverSpecifyValue(userTask)
                .map(value -> value.stream()
                        .map(s -> Optional.ofNullable(JSON.parseObject(s).getString("value"))
                                .orElse(null))
                        .filter(Objects::nonNull)
                        .collect(Collectors.toList())).orElse(Collections.emptyList());
    }

    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException {
        this.applicationContext = context;
    }
}
