package tech.easyflow.agent.service.impl;

import com.mybatisflex.core.query.QueryWrapper;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import tech.easyflow.agent.entity.Agent;
import tech.easyflow.agent.service.AgentApprovalStateService;
import tech.easyflow.ai.enums.PublishStatus;
import tech.easyflow.approval.entity.ApprovalInstance;
import tech.easyflow.approval.enums.ApprovalActionType;
import tech.easyflow.approval.enums.ApprovalInstanceStatus;
import tech.easyflow.approval.enums.ApprovalResourceType;
import tech.easyflow.approval.mapper.ApprovalInstanceMapper;

import java.math.BigInteger;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * Agent 审批状态派生服务实现。
 */
@Service
public class AgentApprovalStateServiceImpl implements AgentApprovalStateService {

    private final ApprovalInstanceMapper approvalInstanceMapper;

    /**
     * 创建 Agent 审批状态派生服务。
     *
     * @param approvalInstanceMapper 审批实例 Mapper
     */
    public AgentApprovalStateServiceImpl(ApprovalInstanceMapper approvalInstanceMapper) {
        this.approvalInstanceMapper = approvalInstanceMapper;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void fillAgentApprovalState(Agent agent) {
        fillAgentApprovalState(agent == null ? List.of() : List.of(agent));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void fillAgentApprovalState(Collection<Agent> agents) {
        if (CollectionUtils.isEmpty(agents)) {
            return;
        }
        List<Agent> validAgents = agents.stream().filter(Objects::nonNull).toList();
        if (validAgents.isEmpty()) {
            return;
        }
        Map<BigInteger, ApprovalInstance> instanceMap = loadInstanceMap(validAgents, Agent::getCurrentApprovalInstanceId);
        for (Agent agent : validAgents) {
            fillOne(agent, instanceMap.get(agent.getCurrentApprovalInstanceId()));
        }
    }

    private void fillOne(Agent agent, ApprovalInstance instance) {
        PublishStatus currentStatus = PublishStatus.from(agent.getPublishStatus());
        if (!isValidCurrentInstance(instance)) {
            agent.setApprovalPending(false);
            agent.setCurrentApprovalActionType(null);
            agent.setDisplayPublishStatus(currentStatus.getCode());
            return;
        }
        ApprovalInstanceStatus instanceStatus = ApprovalInstanceStatus.from(instance.getStatus());
        if (instanceStatus.isFinished()) {
            agent.setApprovalPending(false);
            agent.setCurrentApprovalActionType(null);
            agent.setDisplayPublishStatus(currentStatus.getCode());
            return;
        }
        ApprovalActionType actionType = ApprovalActionType.from(instance.getActionType());
        agent.setApprovalPending(true);
        agent.setCurrentApprovalActionType(actionType.getCode());
        agent.setDisplayPublishStatus(resolveDisplayStatusWithActiveInstance(currentStatus, actionType).getCode());
    }

    private Map<BigInteger, ApprovalInstance> loadInstanceMap(Collection<Agent> agents,
                                                             Function<Agent, BigInteger> instanceIdGetter) {
        Set<BigInteger> instanceIds = agents.stream()
                .map(instanceIdGetter)
                .filter(Objects::nonNull)
                .collect(Collectors.toCollection(LinkedHashSet::new));
        if (instanceIds.isEmpty()) {
            return Collections.emptyMap();
        }
        List<ApprovalInstance> instances = approvalInstanceMapper.selectListByQuery(
                QueryWrapper.create().in(ApprovalInstance::getId, instanceIds)
        );
        return instances.stream().collect(Collectors.toMap(ApprovalInstance::getId, Function.identity()));
    }

    private boolean isValidCurrentInstance(ApprovalInstance instance) {
        return instance != null && ApprovalResourceType.AGENT.getCode().equals(instance.getResourceType());
    }

    private PublishStatus resolveDisplayStatusWithActiveInstance(PublishStatus currentStatus,
                                                                 ApprovalActionType actionType) {
        if (currentStatus == PublishStatus.PUBLISH_PENDING
                || currentStatus == PublishStatus.OFFLINE_PENDING
                || currentStatus == PublishStatus.DELETE_PENDING) {
            return currentStatus;
        }
        return switch (actionType) {
            case PUBLISH -> PublishStatus.PUBLISH_PENDING;
            case OFFLINE -> PublishStatus.OFFLINE_PENDING;
            case DELETE -> PublishStatus.DELETE_PENDING;
        };
    }
}
