package com.easyagents.federation.sql.api;

import com.easyagents.federation.sql.adapter.FederationSqlAdapterProvider;
import com.easyagents.federation.sql.adapter.FederationSqlAdapterRegistry;
import com.easyagents.federation.sql.compile.FederationSqlPolicy;
import com.easyagents.federation.sql.execute.FederationQueryAdmissionController;
import com.easyagents.federation.sql.execute.LocalFederationQueryAdmissionController;
import com.easyagents.federation.sql.federation.FederationExecutionPolicy;
import com.easyagents.federation.sql.federation.FederationTableStatisticsProvider;
import com.easyagents.federation.sql.runtime.DefaultFederationSqlEngine;
import com.easyagents.federation.sql.runtime.DefaultFederationSourceManager;
import com.easyagents.federation.sql.source.FederationDataSourceResolver;
import com.easyagents.federation.sql.source.FederationSourceStateProvider;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.time.Duration;

/**
 * 使用显式依赖构建独立 FederationSqlEngine 的入口。
 */
public final class FederationSqlEngines {

    private FederationSqlEngines() {
    }

    /**
     * 创建 Engine Builder。
     *
     * @return Builder
     */
    public static Builder builder() {
        return new Builder();
    }

    /**
     * FederationSqlEngine 的轻量配置 Builder。
     */
    public static final class Builder {

        private final List<FederationSqlAdapterProvider> adapters = new ArrayList<>();
        private final List<FederationSqlPolicy> policies = new ArrayList<>();
        private FederationDataSourceResolver resolver;
        private FederationSourceStateProvider stateProvider = FederationSourceStateProvider.none();
        private FederationQueryAdmissionController admissionController =
            new LocalFederationQueryAdmissionController(64);
        private int maximumPlanCacheEntries = 1024;
        private long maximumPlanCacheWeightBytes = 64L * 1024L * 1024L;
        private Duration planCacheTimeToLive = Duration.ofMinutes(30);
        private int maximumConcurrentCompilations = Math.max(
            1,
            Math.min(8, Runtime.getRuntime().availableProcessors())
        );
        private boolean crossSourceEnabled = true;
        private FederationExecutionPolicy executionPolicy = FederationExecutionPolicy.basic();
        private long maximumNodeIntermediateBytes = 512L * 1024L * 1024L;
        private FederationTableStatisticsProvider statisticsProvider;
        private ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

        private Builder() {
        }

        /**
         * 设置调用方 DataSource Resolver。
         *
         * @param resolver Resolver
         * @return 当前 Builder
         */
        public Builder dataSourceResolver(FederationDataSourceResolver resolver) {
            this.resolver = Objects.requireNonNull(resolver, "resolver must not be null");
            return this;
        }

        /**
         * 显式注册 Adapter；同 id 时覆盖 ServiceLoader 实现。
         *
         * @param adapter Adapter Provider
         * @return 当前 Builder
         */
        public Builder adapter(FederationSqlAdapterProvider adapter) {
            this.adapters.add(Objects.requireNonNull(adapter, "adapter must not be null"));
            return this;
        }

        /**
         * 增加 SQL 策略。
         *
         * @param policy 策略
         * @return 当前 Builder
         */
        public Builder policy(FederationSqlPolicy policy) {
            this.policies.add(Objects.requireNonNull(policy, "policy must not be null"));
            return this;
        }

        /**
         * 设置共享状态 Provider。
         *
         * @param stateProvider 状态 Provider
         * @return 当前 Builder
         */
        public Builder stateProvider(FederationSourceStateProvider stateProvider) {
            this.stateProvider = Objects.requireNonNull(stateProvider, "stateProvider must not be null");
            return this;
        }

        /**
         * 设置查询准入控制器。
         *
         * @param admissionController 准入控制器
         * @return 当前 Builder
         */
        public Builder admissionController(FederationQueryAdmissionController admissionController) {
            this.admissionController = Objects.requireNonNull(
                admissionController,
                "admissionController must not be null"
            );
            return this;
        }

        /**
         * 设置计划缓存最大条目数。
         *
         * @param maximumPlanCacheEntries 最大条目数
         * @return 当前 Builder
         */
        public Builder maximumPlanCacheEntries(int maximumPlanCacheEntries) {
            if (maximumPlanCacheEntries <= 0) {
                throw new IllegalArgumentException("maximumPlanCacheEntries must be positive");
            }
            this.maximumPlanCacheEntries = maximumPlanCacheEntries;
            return this;
        }

        /**
         * 设置计划缓存最大估算权重。
         *
         * @param maximumPlanCacheWeightBytes 最大估算字节数
         * @return 当前 Builder
         */
        public Builder maximumPlanCacheWeightBytes(long maximumPlanCacheWeightBytes) {
            if (maximumPlanCacheWeightBytes <= 0) {
                throw new IllegalArgumentException("maximumPlanCacheWeightBytes must be positive");
            }
            this.maximumPlanCacheWeightBytes = maximumPlanCacheWeightBytes;
            return this;
        }

        /**
         * 设置计划缓存条目存活时间。
         *
         * @param planCacheTimeToLive 存活时间
         * @return 当前 Builder
         */
        public Builder planCacheTimeToLive(Duration planCacheTimeToLive) {
            if (planCacheTimeToLive == null
                || planCacheTimeToLive.isZero()
                || planCacheTimeToLive.isNegative()) {
                throw new IllegalArgumentException("planCacheTimeToLive must be positive");
            }
            this.planCacheTimeToLive = planCacheTimeToLive;
            return this;
        }

        /**
         * 设置 Calcite 冷编译最大并发数。
         *
         * @param maximumConcurrentCompilations 最大并发冷编译数
         * @return 当前 Builder
         */
        public Builder maximumConcurrentCompilations(int maximumConcurrentCompilations) {
            if (maximumConcurrentCompilations <= 0) {
                throw new IllegalArgumentException("maximumConcurrentCompilations must be positive");
            }
            this.maximumConcurrentCompilations = maximumConcurrentCompilations;
            return this;
        }

        /**
         * 设置联邦执行开关。
         *
         * @param enabled 是否开启
         * @return 当前 Builder
         */
        public Builder crossSourceEnabled(boolean enabled) {
            this.crossSourceEnabled = enabled;
            return this;
        }

        /**
         * 设置 Engine 级联邦资源硬上限。
         *
         * @param executionPolicy 资源策略
         * @return 当前 Builder
         */
        public Builder federationExecutionPolicy(FederationExecutionPolicy executionPolicy) {
            this.executionPolicy = Objects.requireNonNull(
                executionPolicy,
                "executionPolicy must not be null"
            );
            return this;
        }

        /**
         * 设置节点同时预留的联邦中间结果内存总上限。
         *
         * @param maximumNodeIntermediateBytes 节点内存上限
         * @return 当前 Builder
         */
        public Builder maximumNodeIntermediateBytes(long maximumNodeIntermediateBytes) {
            if (maximumNodeIntermediateBytes <= 0L) {
                throw new IllegalArgumentException(
                    "maximumNodeIntermediateBytes must be positive"
                );
            }
            this.maximumNodeIntermediateBytes = maximumNodeIntermediateBytes;
            return this;
        }

        /**
         * 设置联邦表统计 Provider，覆盖引擎内建的 Adapter 自动采集能力。
         *
         * @param statisticsProvider 调用方完全托管的只读统计快照 Provider
         * @return 当前 Builder
         */
        public Builder tableStatisticsProvider(
            FederationTableStatisticsProvider statisticsProvider
        ) {
            this.statisticsProvider = Objects.requireNonNull(
                statisticsProvider,
                "statisticsProvider must not be null"
            );
            return this;
        }

        /**
         * 设置 ServiceLoader 类加载器。
         *
         * @param classLoader 类加载器
         * @return 当前 Builder
         */
        public Builder classLoader(ClassLoader classLoader) {
            this.classLoader = Objects.requireNonNull(classLoader, "classLoader must not be null");
            return this;
        }

        /**
         * 构建独立 Engine。
         *
         * @return Engine
         */
        public FederationSqlEngine build() {
            if (resolver == null) {
                throw new IllegalStateException("dataSourceResolver must be configured");
            }
            FederationSqlAdapterRegistry registry = new FederationSqlAdapterRegistry(adapters, classLoader);
            DefaultFederationSourceManager sourceManager = new DefaultFederationSourceManager(
                resolver,
                registry,
                stateProvider
            );
            return new DefaultFederationSqlEngine(
                sourceManager,
                admissionController,
                policies,
                maximumPlanCacheEntries,
                maximumConcurrentCompilations,
                crossSourceEnabled,
                executionPolicy,
                maximumPlanCacheWeightBytes,
                planCacheTimeToLive,
                statisticsProvider,
                maximumNodeIntermediateBytes
            );
        }
    }
}
