package tech.easyflow.publicapi.service;

import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import tech.easyflow.ai.easyagentsflow.entity.ChainInfo;
import tech.easyflow.ai.easyagentsflow.entity.NodeInfo;
import tech.easyflow.publicapi.dto.PublicWorkflowChainStatus;
import tech.easyflow.publicapi.dto.PublicWorkflowExecutionStatus;
import tech.easyflow.publicapi.dto.PublicWorkflowNodeStatus;
import tech.easyflow.publicapi.dto.PublicWorkflowStatusError;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 将内部工作流执行错误转换为 Public API 安全状态。
 */
@Service
public class PublicWorkflowStatusSanitizer {

    private static final String CHAIN_FAILED_MESSAGE =
            "工作流执行失败，请检查输入或稍后重试";
    private static final String NODE_FAILED_MESSAGE =
            "节点执行失败，请检查输入或稍后重试";

    /**
     * 复制执行状态并移除异常类名、底层地址和内部错误详情。
     *
     * @param source 内部执行状态
     * @return 可公开状态
     */
    public PublicWorkflowChainStatus sanitize(ChainInfo source) {
        if (source == null) {
            throw new IllegalArgumentException(
                    "source must not be null");
        }
        PublicWorkflowExecutionStatus chainStatus =
                PublicWorkflowExecutionStatus.fromChainStatus(
                        source.getStatus());

        Map<String, PublicWorkflowNodeStatus> safeNodes =
                new LinkedHashMap<>();
        PublicWorkflowStatusError firstNodeError = null;
        if (source.getNodes() != null) {
            for (Map.Entry<String, NodeInfo> entry
                    : source.getNodes().entrySet()) {
                PublicWorkflowNodeStatus safeNode = copyNode(
                        entry.getValue());
                safeNodes.put(entry.getKey(), safeNode);
                if (firstNodeError == null
                        && StringUtils.hasText(safeNode.message())) {
                    firstNodeError = new PublicWorkflowStatusError(
                            "NODE_EXECUTION_FAILED",
                            safeNode.message(),
                            safeNode.nodeId(),
                            safeNode.nodeName(),
                            isRetryable(safeNode.status()));
                }
            }
        }

        String message = null;
        PublicWorkflowStatusError error = null;
        if (StringUtils.hasText(source.getMessage())) {
            message = chainMessage(chainStatus);
            error = new PublicWorkflowStatusError(
                    "WORKFLOW_EXECUTION_FAILED",
                    message,
                    firstNodeError == null
                            ? null
                            : firstNodeError.getNodeId(),
                    firstNodeError == null
                            ? null
                            : firstNodeError.getNodeName(),
                    isRetryable(chainStatus));
        } else if (firstNodeError != null) {
            error = firstNodeError;
        }
        return new PublicWorkflowChainStatus(
                source.getExecuteId(),
                chainStatus,
                chainStatus.isTerminal(),
                message,
                source.getResult(),
                safeNodes,
                error);
    }

    /**
     * 复制并脱敏单个节点状态。
     *
     * @param source 内部节点状态
     * @return 安全节点状态
     */
    private PublicWorkflowNodeStatus copyNode(NodeInfo source) {
        if (source == null) {
            return new PublicWorkflowNodeStatus(
                    null,
                    null,
                    PublicWorkflowExecutionStatus.UNKNOWN,
                    null,
                    null,
                    null);
        }
        return new PublicWorkflowNodeStatus(
                source.getNodeId(),
                source.getNodeName(),
                PublicWorkflowExecutionStatus.fromNodeStatus(
                        source.getStatus()),
                StringUtils.hasText(source.getMessage())
                        ? NODE_FAILED_MESSAGE
                        : null,
                source.getResult(),
                source.getSuspendForParameters());
    }

    /**
     * 根据工作流状态生成安全消息。
     *
     * @param status 可读状态
     * @return 安全消息
     */
    private String chainMessage(
            PublicWorkflowExecutionStatus status) {
        if (status == PublicWorkflowExecutionStatus.CANCELLED) {
            return "工作流执行已取消";
        }
        return CHAIN_FAILED_MESSAGE;
    }

    /**
     * 判断执行状态是否仍可能由运行时继续处理。
     *
     * @param status 可读状态
     * @return 是否可重试
     */
    private boolean isRetryable(
            PublicWorkflowExecutionStatus status) {
        return status == PublicWorkflowExecutionStatus.ERROR;
    }
}
