package com.easyagents.federation.sql.federation;

import com.easyagents.federation.sql.source.SourceId;
import java.io.Serializable;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

/**
 * 将查询范围内的一个 Binding 绑定到已经登记的物理数据源。
 *
 * @param sourceId 物理数据源标识
 * @param minimumRevision 查询要求的最低 Definition 版本
 * @param schemaMappings 查询逻辑 Schema 到物理 Definition 逻辑 Schema 的映射；空映射表示同名暴露全部 Schema
 */
public record FederationSourceBindingDefinition(
    SourceId sourceId,
    long minimumRevision,
    Map<String, String> schemaMappings
) implements Serializable {

    /**
     * 校验并创建不可变 Binding 定义。
     */
    public FederationSourceBindingDefinition {
        if (sourceId == null) {
            throw new IllegalArgumentException("sourceId must not be null");
        }
        if (minimumRevision < 0) {
            throw new IllegalArgumentException("minimumRevision must not be negative");
        }
        LinkedHashMap<String, String> copied = new LinkedHashMap<>();
        Set<String> normalizedSchemaNames = new HashSet<>();
        if (schemaMappings != null) {
            schemaMappings.forEach((querySchema, sourceSchema) -> {
                if (querySchema == null || querySchema.isBlank()
                    || sourceSchema == null || sourceSchema.isBlank()) {
                    throw new IllegalArgumentException("schema mapping names must not be blank");
                }
                if (!normalizedSchemaNames.add(querySchema.toUpperCase(Locale.ROOT))) {
                    throw new IllegalArgumentException(
                        "query schema names must be unique ignoring unquoted identifier case"
                    );
                }
                copied.put(querySchema, sourceSchema);
            });
        }
        schemaMappings = Collections.unmodifiableMap(copied);
    }

    /**
     * 创建不改写 Schema 名称的物理数据源 Binding。
     *
     * @param sourceId 物理数据源标识
     * @param minimumRevision 最低 Definition 版本
     * @return Binding 定义
     */
    public static FederationSourceBindingDefinition of(
        SourceId sourceId,
        long minimumRevision
    ) {
        return new FederationSourceBindingDefinition(sourceId, minimumRevision, Map.of());
    }

    /**
     * 创建显式映射查询 Schema 的物理数据源 Binding。
     *
     * @param sourceId 物理数据源标识
     * @param minimumRevision 最低 Definition 版本
     * @param schemaMappings 查询逻辑 Schema 到 Definition 逻辑 Schema 的映射
     * @return Binding 定义
     */
    public static FederationSourceBindingDefinition of(
        SourceId sourceId,
        long minimumRevision,
        Map<String, String> schemaMappings
    ) {
        return new FederationSourceBindingDefinition(
            sourceId,
            minimumRevision,
            schemaMappings
        );
    }
}
