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

import cn.axzo.workflow.common.enums.ApproverSpecifyEnum;
import cn.axzo.workflow.common.enums.BpmnFlowNodeType;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
import cn.axzo.workflow.core.repository.entity.ExtAxProcessLog;
import cn.axzo.workflow.core.service.ExtAxProcessLogService;
import lombok.AllArgsConstructor;
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 java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_CARBON_COPY;
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.DELETED;

/**
 * 基于前序节点的任务审批人选择器（除非抄送节点）
 *
 * @author wangli
 * @since 2025-08-18 15:11
 */
@Slf4j
@Component
@AllArgsConstructor
public class BasedPreAllNodeTaskAssigneeSelector extends AbstractBpmnTaskAssigneeSelector {
    private final ExtAxProcessLogService processLogService;

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

    @Override
    public List<BpmnTaskDelegateAssigner> select(FlowElement flowElement, DelegateExecution execution, Boolean throwException) {
        ExtAxProcessLog query = new ExtAxProcessLog();
        query.setProcessInstanceId(execution.getProcessInstanceId());
        List<ExtAxProcessLog> logs = processLogService.genericQuery(query);
        if (CollectionUtils.isEmpty(logs)) {
            return Collections.emptyList();
        }
        return logs.stream()
                .filter(i -> !Objects.equals(BpmnFlowNodeType.valueOfType(i.getNodeType()), NODE_CARBON_COPY))
                .filter(i -> !Objects.equals(i.getStatus(), DELETED.getStatus()))
                .flatMap(log -> !CollectionUtils.isEmpty(log.getAssigneeFull()) ? log.getAssigneeFull().stream() : Stream.empty())
                .collect(Collectors.toList());
    }
}
