package com.magistr.app.config.tenant;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;

/**
 * Квитанция об атомарном изменении tenant Secret.
 *
 * <p>Снимки конфигурации копируются глубоко и сортируются по домену. Это позволяет
 * безопасно использовать квитанцию для компенсации и проверки ожидаемого состояния.</p>
 */
public final class TenantSecretUpdateReceipt {

    private static final Comparator<TenantConfig> BY_DOMAIN = Comparator.comparing(
            TenantConfig::getDomain,
            Comparator.nullsFirst(String::compareTo)
    );

    private final boolean persisted;
    private final boolean changed;
    private final String committedResourceVersion;
    private final List<TenantConfig> previousTenants;
    private final List<TenantConfig> committedTenants;

    public TenantSecretUpdateReceipt(boolean persisted,
                                     boolean changed,
                                     String committedResourceVersion,
                                     List<TenantConfig> previousTenants,
                                     List<TenantConfig> committedTenants) {
        this.persisted = persisted;
        this.changed = changed;
        this.committedResourceVersion = committedResourceVersion;
        this.previousTenants = copyAndSort(previousTenants);
        this.committedTenants = copyAndSort(committedTenants);
    }

    public boolean persisted() {
        return persisted;
    }

    /**
     * Возвращает {@code true}, только если хранилище доказало владение подтверждённой
     * записанной версией. После неоднозначного результата повторное чтение может подтвердить
     * целевое состояние, но оставляет этот признак {@code false}, чтобы запретить опасную
     * автоматическую компенсацию.
     */
    public boolean changed() {
        return changed;
    }

    public String committedResourceVersion() {
        return committedResourceVersion;
    }

    public List<TenantConfig> previousTenants() {
        return copyAndSort(previousTenants);
    }

    public List<TenantConfig> committedTenants() {
        return copyAndSort(committedTenants);
    }

    static List<TenantConfig> copyAndSort(List<TenantConfig> tenants) {
        Objects.requireNonNull(tenants, "Список конфигураций тенантов не задан");
        List<TenantConfig> result = new ArrayList<>(tenants.size());
        for (TenantConfig tenant : tenants) {
            result.add(copyOf(Objects.requireNonNull(tenant, "Конфигурация тенанта не задана")));
        }
        result.sort(BY_DOMAIN);
        return List.copyOf(result);
    }

    static TenantConfig copyOf(TenantConfig source) {
        return new TenantConfig(
                source.getName(),
                source.getDomain(),
                source.getUrl(),
                source.getUsername(),
                source.getPassword()
        );
    }

    @Override
    public String toString() {
        return "TenantSecretUpdateReceipt{" +
                "persisted=" + persisted +
                ", changed=" + changed +
                ", committedResourceVersion='" + committedResourceVersion + '\'' +
                ", previousTenantCount=" + previousTenants.size() +
                ", committedTenantCount=" + committedTenants.size() +
                '}';
    }
}
