package com.easyagents.federation.sql.compile;

import com.easyagents.federation.sql.adapter.AdapterCompatibility;
import com.easyagents.federation.sql.execute.FederationColumn;
import com.easyagents.federation.sql.federation.FederationFragmentPlan;
import com.easyagents.federation.sql.federation.FederationJoinOptimization;
import com.easyagents.federation.sql.federation.FederationQueryMode;
import com.easyagents.federation.sql.federation.FederationQueryScopeDefinition;
import com.easyagents.federation.sql.federation.FederationSourceRuntimeIdentity;
import com.easyagents.federation.sql.source.SourceId;
import java.time.Instant;
import java.util.List;
import java.util.Set;
import org.apache.calcite.rel.RelRoot;
import org.apache.calcite.sql.SqlNode;

/**
 * Engine 签发的节点本地 SQL 编译计划。
 *
 * <p>该接口仅用于读取编译事实。调用方不能自行创建可执行计划，且计划只能交回
 * 签发它的 Engine 实例执行。</p>
 */
public interface FederationSqlPlan {

    /**
     * 返回主数据源。
     *
     * @return 主数据源
     */
    SourceId sourceId();

    /**
     * 返回编译时使用的不可变查询范围。
     *
     * @return 查询范围
     */
    FederationQueryScopeDefinition queryScope();

    /**
     * 返回根据实际引用源确定的查询模式。
     *
     * @return 查询模式
     */
    FederationQueryMode queryMode();

    /**
     * 返回数据源版本。
     *
     * @return 数据源版本
     */
    long sourceRevision();

    /**
     * 返回 Calcite 规范化 SQL。
     *
     * @return Calcite 规范化 SQL
     */
    String normalizedSql();

    /**
     * 返回单源目标数据库参数化 SQL。
     *
     * <p>联邦计划应读取 {@link #fragments()}；本兼容视图不代表任一数据库可执行 SQL。</p>
     *
     * @return 单源目标 SQL，或联邦调用方原始 SQL 兼容视图
     */
    String executableSql();

    /**
     * 返回 Calcite 已校验 SQL 节点。
     *
     * @return Calcite 已校验 SQL 节点
     */
    SqlNode sqlNode();

    /**
     * 返回 Calcite 关系计划。
     *
     * @return Calcite 关系计划
     */
    RelRoot relRoot();

    /**
     * 返回动态参数数量。
     *
     * @return 动态参数数量
     */
    int parameterCount();

    /**
     * 返回编译时声明的原始 JDBC 参数类型。
     *
     * @return JDBC 参数类型；未显式声明时为空
     */
    List<Integer> parameterJdbcTypes();

    /**
     * 返回目标 SQL 占位符到原始参数的零基索引映射。
     *
     * @return 参数映射
     */
    List<Integer> parameterMapping();

    /**
     * 返回物理数据源分片；单源计划也包含一个分片。
     *
     * @return 分片列表
     */
    List<FederationFragmentPlan> fragments();

    /**
     * 返回跨源 Join 的优化选择。
     *
     * @return 不可变 Join 优化列表
     */
    default List<FederationJoinOptimization> joinOptimizations() {
        return List.of();
    }

    /**
     * 返回实际引用 Binding 对应的节点本地运行身份。
     *
     * @return 运行身份列表
     */
    List<FederationSourceRuntimeIdentity> sourceRuntimeIdentities();

    /**
     * 返回查询范围的稳定校验和。
     *
     * @return Scope 校验和
     */
    String scopeChecksum();

    /**
     * 返回结果列。
     *
     * @return 结果列
     */
    List<FederationColumn> columns();

    /**
     * 返回引用的数据源集合。
     *
     * @return 引用的数据源集合
     */
    Set<SourceId> referencedSources();

    /**
     * 返回 Adapter 兼容性。
     *
     * @return Adapter 兼容性
     */
    AdapterCompatibility compatibility();

    /**
     * 返回是否允许直接执行。
     *
     * @return 是否允许直接执行
     */
    boolean executable();

    /**
     * 返回编译时的数据源 Definition 校验和。
     *
     * @return Definition 校验和
     */
    String sourceChecksum();

    /**
     * 返回编译时的 Adapter 标识。
     *
     * @return Adapter 标识
     */
    String adapterId();

    /**
     * 返回编译时的数据库与驱动指纹。
     *
     * @return 运行指纹摘要
     */
    String runtimeFingerprint();

    /**
     * 返回该计划所依赖统计快照的最早失效时间。
     *
     * @return 最早失效时间；未使用有期限统计时为 {@link Instant#MAX}
     */
    default Instant statisticsValidUntil() {
        return Instant.MAX;
    }
}
