package de.gecheckt.pdf.umbenenner.application.validation.editor;

import java.util.Optional;

import de.gecheckt.pdf.umbenenner.application.config.provider.AiProviderFamily;
import de.gecheckt.pdf.umbenenner.application.port.out.modelcatalog.EffectiveApiKeyDescriptor;

/**
 * Outbound-Port für die Auflösung der API-Key-Herkunft pro Provider-Familie.
 * <p>
 * Gibt zurück, aus welcher Quelle der effektive API-Schlüssel für einen angegebenen Provider
 * stammt. Die Vorrangregel lautet:
 * <ol>
 *   <li>Providerspezifische Umgebungsvariable (höchste Priorität)</li>
 *   <li>Bei {@code openai-compatible}: zusätzlich die Legacy-Umgebungsvariable als Fallback</li>
 *   <li>Property-Wert aus der {@code .properties}-Datei</li>
 *   <li>{@link de.gecheckt.pdf.umbenenner.application.port.out.modelcatalog.ApiKeyOrigin#ABSENT}
 *       wenn keine Quelle einen Wert liefert</li>
 * </ol>
 * <p>
 * Der Port kennt keine Datei-Inhalte und kein Property-Parsing; er liest ausschließlich
 * Umgebungsvariablen. Der Property-Wert wird von der GUI als separates Eingabeargument übergeben
 * und vom Validator mit dem Port-Ergebnis kombiniert.
 * <p>
 * Implementierungen dieses Ports liegen im Adapter-Out-Modul.
 */
@FunctionalInterface
public interface ApiKeyResolutionPort {

    /**
     * Ermittelt die Herkunft des effektiven API-Schlüssels für den angegebenen Provider.
     * <p>
     * Gibt nur dann {@link de.gecheckt.pdf.umbenenner.application.port.out.modelcatalog.ApiKeyOrigin#FROM_PROPERTY_FILE}
     * zurück, wenn {@code propertyValue} nicht leer ist und keine Umgebungsvariable greift.
     * Gibt {@link de.gecheckt.pdf.umbenenner.application.port.out.modelcatalog.ApiKeyOrigin#ABSENT} zurück,
     * wenn weder Umgebungsvariable noch {@code propertyValue} einen Wert liefern.
     *
     * @param family         die Provider-Familie; darf nicht {@code null} sein
     * @param propertyValue  aktueller Property-Wert aus dem Editor (kann leer sein); darf nicht {@code null} sein
     * @return der Descriptor für die effektive Schlüsselherkunft; nie {@code null}
     */
    EffectiveApiKeyDescriptor resolve(AiProviderFamily family, String propertyValue);

    /**
     * Liefert den effektiven API-Schlüssel-Rohwert anhand derselben Vorrangregel wie {@link #resolve}.
     * <p>
     * Dient technischen Tests wie dem Modellkatalogabruf, die den tatsächlichen Schlüssel im
     * HTTP-Header benötigen. Die Herkunft selbst wird nicht mit zurückgegeben – dafür ist
     * {@link #resolve} zuständig.
     * <p>
     * Diese Default-Implementierung deckt den Fall ab, in dem ein Adapter ausschließlich die
     * Property-Datei kennt: liefert {@link #resolve} {@code ABSENT}, wird ein leerer Optional
     * zurückgegeben; andernfalls wird der nicht-leere Property-Wert geliefert. Adapter, die
     * Umgebungsvariablen lesen, müssen diese Methode überschreiben, damit der ENV-Wert auch
     * tatsächlich an HTTP-Aufrufer durchgereicht wird.
     *
     * @param family        die Provider-Familie; darf nicht {@code null} sein
     * @param propertyValue aktueller Property-Wert aus dem Editor (kann leer sein); darf nicht {@code null} sein
     * @return der effektive Schlüssel-Rohwert, falls eine der Quellen einen Wert liefert; sonst leer
     */
    default Optional<String> resolveEffectiveApiKeyValue(AiProviderFamily family, String propertyValue) {
        EffectiveApiKeyDescriptor descriptor = resolve(family, propertyValue);
        if (descriptor.isAbsent()) {
            return Optional.empty();
        }
        if (propertyValue != null && !propertyValue.isBlank()) {
            return Optional.of(propertyValue);
        }
        return Optional.empty();
    }
}
