package com.easyagents.federation.sql.federation;

import java.io.Serializable;
import java.util.List;

/**
 * 一次跨源 Join 的优化结果。
 *
 * @param stageIndex 执行阶段序号，从 1 开始
 * @param leftBindings 左输入包含的 Binding 集合
 * @param rightBindings 右输入包含的 Binding 集合
 * @param buildBinding 哈希表构建侧 Binding
 * @param algorithm Join 算法
 * @param reason 选择原因
 * @param estimatedBuildBytes 构建侧估算字节数
 */
public record FederationJoinOptimization(
    int stageIndex,
    List<String> leftBindings,
    List<String> rightBindings,
    String buildBinding,
    FederationJoinAlgorithm algorithm,
    FederationJoinSelectionReason reason,
    double estimatedBuildBytes
) implements Serializable {

    /**
     * 校验并规范化优化结果。
     */
    public FederationJoinOptimization {
        if (stageIndex <= 0) {
            throw new IllegalArgumentException("stageIndex must be positive");
        }
        leftBindings = List.copyOf(leftBindings == null ? List.of() : leftBindings);
        rightBindings = List.copyOf(rightBindings == null ? List.of() : rightBindings);
        if (leftBindings.isEmpty() || rightBindings.isEmpty()
            || leftBindings.stream().anyMatch(value -> value == null || value.isBlank())
            || rightBindings.stream().anyMatch(value -> value == null || value.isBlank())
            || buildBinding == null || buildBinding.isBlank()) {
            throw new IllegalArgumentException("join binding names must not be blank");
        }
        if (!Double.isFinite(estimatedBuildBytes) || estimatedBuildBytes < 0) {
            throw new IllegalArgumentException(
                "estimatedBuildBytes must be finite and non-negative"
            );
        }
        algorithm = algorithm == null ? FederationJoinAlgorithm.HASH_JOIN : algorithm;
        reason = reason == null
            ? FederationJoinSelectionReason.INCOMPLETE_STATISTICS
            : reason;
    }

    /**
     * 创建兼容的两输入单阶段优化结果。
     *
     * @param leftBinding 左输入 Binding
     * @param rightBinding 右输入 Binding
     * @param buildBinding 哈希构建侧 Binding
     * @param algorithm Join 算法
     * @param reason 选择原因
     * @param estimatedBuildBytes 预计构建字节数
     */
    public FederationJoinOptimization(
        String leftBinding,
        String rightBinding,
        String buildBinding,
        FederationJoinAlgorithm algorithm,
        FederationJoinSelectionReason reason,
        double estimatedBuildBytes
    ) {
        this(
            1,
            List.of(leftBinding),
            List.of(rightBinding),
            buildBinding,
            algorithm,
            reason,
            estimatedBuildBytes
        );
    }

    /**
     * 返回左输入的紧凑展示名称。
     *
     * @return 单个 Binding 或多个 Binding 的组合名称
     */
    public String leftBinding() {
        return String.join(" + ", leftBindings);
    }

    /**
     * 返回右输入的紧凑展示名称。
     *
     * @return 单个 Binding 或多个 Binding 的组合名称
     */
    public String rightBinding() {
        return String.join(" + ", rightBindings);
    }
}
