package com.easyagents.federation.sql.compile;

import com.easyagents.federation.sql.adapter.AdapterCompatibility;
import com.easyagents.federation.sql.federation.FederationQueryMode;
import com.easyagents.federation.sql.federation.FederationJoinOptimization;
import com.easyagents.federation.sql.federation.FederationStatisticsStatus;
import com.easyagents.federation.sql.source.SourceId;
import java.io.Serializable;
import java.util.List;
import java.util.Set;

/**
 * 不含节点本地 Calcite/JDBC 对象的 Explain 结果。
 *
 * @param level Explain 深度
 * @param queryMode 实际查询模式
 * @param statisticsStatus 成本统计完整性与时效状态
 * @param estimateAvailable 聚合成本数值是否为有效估算
 * @param estimatedTransferBytes 预计从物理源搬运的总字节数
 * @param estimatedLocalMemoryBytes 本地 Join 构建侧估算内存字节数
 * @param joinOptimizations 跨源 Join 优化选择
 * @param normalizedSql Calcite 规范化 SQL
 * @param executableSql 单源目标方言 SQL；联邦计划仅为兼容视图，应读取 fragments
 * @param relationalPlan 关系计划文本
 * @param executionPlan 实际单源下推或联邦本地执行计划文本
 * @param fragments 物理分片与可选数据库计划
 * @param referencedSources 引用的数据源
 * @param compatibility Adapter 兼容性
 * @param executable 是否允许执行
 * @param planCacheHit 是否命中节点本地计划缓存
 * @param diagnostic 诊断说明
 */
public record SqlExplainResult(
    SqlExplainLevel level,
    FederationQueryMode queryMode,
    FederationStatisticsStatus statisticsStatus,
    boolean estimateAvailable,
    double estimatedTransferBytes,
    long estimatedLocalMemoryBytes,
    List<FederationJoinOptimization> joinOptimizations,
    String normalizedSql,
    String executableSql,
    String relationalPlan,
    String executionPlan,
    List<FederationFragmentExplain> fragments,
    Set<SourceId> referencedSources,
    AdapterCompatibility compatibility,
    boolean executable,
    boolean planCacheHit,
    String diagnostic
) implements Serializable {

    /**
     * 防御性复制引用集合。
     */
    public SqlExplainResult {
        level = level == null ? SqlExplainLevel.LOGICAL : level;
        queryMode = queryMode == null ? FederationQueryMode.SINGLE_SOURCE : queryMode;
        statisticsStatus = statisticsStatus == null
            ? FederationStatisticsStatus.MISSING
            : statisticsStatus;
        if (!Double.isFinite(estimatedTransferBytes) || estimatedTransferBytes < 0
            || estimatedLocalMemoryBytes < 0) {
            throw new IllegalArgumentException("Explain cost values must be non-negative");
        }
        joinOptimizations = List.copyOf(
            joinOptimizations == null ? List.of() : joinOptimizations
        );
        fragments = List.copyOf(fragments == null ? List.of() : fragments);
        referencedSources = Set.copyOf(referencedSources);
        diagnostic = diagnostic == null ? "" : diagnostic;
    }

    /**
     * 创建未包含聚合成本字段的兼容 Explain 结果。
     *
     * @param level Explain 深度
     * @param queryMode 查询模式
     * @param normalizedSql 规范化 SQL
     * @param executableSql 可执行 SQL
     * @param relationalPlan 关系计划
     * @param executionPlan 执行计划
     * @param fragments 分片计划
     * @param referencedSources 引用源
     * @param compatibility Adapter 兼容性
     * @param executable 是否可执行
     * @param planCacheHit 是否命中缓存
     * @param diagnostic 诊断信息
     */
    public SqlExplainResult(
        SqlExplainLevel level,
        FederationQueryMode queryMode,
        String normalizedSql,
        String executableSql,
        String relationalPlan,
        String executionPlan,
        List<FederationFragmentExplain> fragments,
        Set<SourceId> referencedSources,
        AdapterCompatibility compatibility,
        boolean executable,
        boolean planCacheHit,
        String diagnostic
    ) {
        this(
            level,
            queryMode,
            FederationStatisticsStatus.MISSING,
            false,
            0D,
            0L,
            List.of(),
            normalizedSql,
            executableSql,
            relationalPlan,
            executionPlan,
            fragments,
            referencedSources,
            compatibility,
            executable,
            planCacheHit,
            diagnostic
        );
    }

    /**
     * 创建旧单源字段视图的兼容 Explain 结果。
     *
     * @param normalizedSql Calcite 规范化 SQL
     * @param executableSql 目标方言 SQL
     * @param relationalPlan 关系计划文本
     * @param referencedSources 引用的数据源
     * @param compatibility Adapter 兼容性
     * @param executable 是否允许执行
     * @param diagnostic 诊断说明
     */
    public SqlExplainResult(
        String normalizedSql,
        String executableSql,
        String relationalPlan,
        Set<SourceId> referencedSources,
        AdapterCompatibility compatibility,
        boolean executable,
        String diagnostic
    ) {
        this(
            SqlExplainLevel.LOGICAL,
            FederationQueryMode.SINGLE_SOURCE,
            FederationStatisticsStatus.MISSING,
            false,
            0D,
            0L,
            List.of(),
            normalizedSql,
            executableSql,
            relationalPlan,
            relationalPlan,
            List.of(),
            referencedSources,
            compatibility,
            executable,
            false,
            diagnostic
        );
    }
}
