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

import java.util.Objects;

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

/**
 * Eingabedaten für den {@link EditorConfigurationValidator}.
 * <p>
 * Enthält den gesamten aktuellen Editorzustand als String-Werte, so wie sie im Editor
 * vorliegen – ohne Parsing, Typumwandlung oder Existenzprüfungen. Der Validator bewertet
 * ausschließlich diese Werte.
 * <p>
 * Pfad-Existenzprüfungen und Roundtrips (SQLite, Prompt-Datei, Netzwerk) sind explizit
 * ausgeschlossen und gehören in spätere technische Gesamtprüfungen.
 * <p>
 * Dieser Record enthält keine JavaFX-Typen und keine Infrastrukturabhängigkeiten.
 *
 * @param activeProviderIdentifier  Rohtextwert von {@code ai.provider.active}
 * @param sourceFolder              Rohtextwert von {@code source.folder}
 * @param targetFolder              Rohtextwert von {@code target.folder}
 * @param sqliteFile                Rohtextwert von {@code sqlite.file}
 * @param promptTemplateFile        Rohtextwert von {@code prompt.template.file}
 * @param maxRetriesTransient       Rohtextwert von {@code max.retries.transient}
 * @param maxPages                  Rohtextwert von {@code max.pages}
 * @param maxTextCharacters         Rohtextwert von {@code max.text.characters}
 * @param maxTitleLength            Rohtextwert von {@code max.title.length}
 * @param claudeBaseUrl             Rohtextwert der Claude-Basis-URL
 * @param claudeModel               Rohtextwert des Claude-Modellnamens
 * @param claudeTimeoutSeconds      Rohtextwert des Claude-Timeouts
 * @param claudeApiKeyDescriptor    API-Key-Herkunft für den Claude-Provider; nie {@code null}
 * @param claudeApiKeyPropertyValue Rohwert des Claude-API-Schlüssels aus der Properties-Datei
 * @param openaiBaseUrl             Rohtextwert der OpenAI-kompatiblen Basis-URL
 * @param openaiModel               Rohtextwert des OpenAI-kompatiblen Modellnamens
 * @param openaiTimeoutSeconds      Rohtextwert des OpenAI-kompatiblen Timeouts
 * @param openaiApiKeyDescriptor    API-Key-Herkunft für den OpenAI-kompatiblen Provider; nie {@code null}
 * @param openaiApiKeyPropertyValue Rohwert des OpenAI-API-Schlüssels aus der Properties-Datei
 */
public record EditorValidationInput(
        String activeProviderIdentifier,
        String sourceFolder,
        String targetFolder,
        String sqliteFile,
        String promptTemplateFile,
        String maxRetriesTransient,
        String maxPages,
        String maxTextCharacters,
        String maxTitleLength,
        String claudeBaseUrl,
        String claudeModel,
        String claudeTimeoutSeconds,
        EffectiveApiKeyDescriptor claudeApiKeyDescriptor,
        String claudeApiKeyPropertyValue,
        String openaiBaseUrl,
        String openaiModel,
        String openaiTimeoutSeconds,
        EffectiveApiKeyDescriptor openaiApiKeyDescriptor,
        String openaiApiKeyPropertyValue) {

    /**
     * Erstellt eine neue Eingabe für den Validator.
     *
     * @param activeProviderIdentifier  aktiver Provider-Bezeichner; {@code null} wird zu leerem String
     * @param sourceFolder              Quellordner-Pfad; {@code null} wird zu leerem String
     * @param targetFolder              Zielordner-Pfad; {@code null} wird zu leerem String
     * @param sqliteFile                SQLite-Dateipfad; {@code null} wird zu leerem String
     * @param promptTemplateFile        Prompt-Dateipfad; {@code null} wird zu leerem String
     * @param maxRetriesTransient       max. transiente Retries; {@code null} wird zu leerem String
     * @param maxPages                  max. Seitenzahl; {@code null} wird zu leerem String
     * @param maxTextCharacters         max. Zeichenzahl; {@code null} wird zu leerem String
     * @param maxTitleLength            max. Titellänge; {@code null} wird zu leerem String
     * @param claudeBaseUrl             Claude-Basis-URL; {@code null} wird zu leerem String
     * @param claudeModel               Claude-Modellname; {@code null} wird zu leerem String
     * @param claudeTimeoutSeconds      Claude-Timeout; {@code null} wird zu leerem String
     * @param claudeApiKeyDescriptor    Claude-API-Key-Herkunft; darf nicht {@code null} sein
     * @param claudeApiKeyPropertyValue Claude-API-Key-Rohwert aus der Properties-Datei; {@code null} wird zu leerem String
     * @param openaiBaseUrl             OpenAI-Basis-URL; {@code null} wird zu leerem String
     * @param openaiModel               OpenAI-Modellname; {@code null} wird zu leerem String
     * @param openaiTimeoutSeconds      OpenAI-Timeout; {@code null} wird zu leerem String
     * @param openaiApiKeyDescriptor    OpenAI-API-Key-Herkunft; darf nicht {@code null} sein
     * @param openaiApiKeyPropertyValue OpenAI-API-Key-Rohwert aus der Properties-Datei; {@code null} wird zu leerem String
     * @throws NullPointerException wenn {@code claudeApiKeyDescriptor} oder {@code openaiApiKeyDescriptor} {@code null} sind
     */
    public EditorValidationInput {
        activeProviderIdentifier = normalizeText(activeProviderIdentifier);
        sourceFolder = normalizeText(sourceFolder);
        targetFolder = normalizeText(targetFolder);
        sqliteFile = normalizeText(sqliteFile);
        promptTemplateFile = normalizeText(promptTemplateFile);
        maxRetriesTransient = normalizeText(maxRetriesTransient);
        maxPages = normalizeText(maxPages);
        maxTextCharacters = normalizeText(maxTextCharacters);
        maxTitleLength = normalizeText(maxTitleLength);
        claudeBaseUrl = normalizeText(claudeBaseUrl);
        claudeModel = normalizeText(claudeModel);
        claudeTimeoutSeconds = normalizeText(claudeTimeoutSeconds);
        claudeApiKeyDescriptor = Objects.requireNonNull(claudeApiKeyDescriptor,
                "claudeApiKeyDescriptor must not be null");
        claudeApiKeyPropertyValue = normalizeText(claudeApiKeyPropertyValue);
        openaiBaseUrl = normalizeText(openaiBaseUrl);
        openaiModel = normalizeText(openaiModel);
        openaiTimeoutSeconds = normalizeText(openaiTimeoutSeconds);
        openaiApiKeyDescriptor = Objects.requireNonNull(openaiApiKeyDescriptor,
                "openaiApiKeyDescriptor must not be null");
        openaiApiKeyPropertyValue = normalizeText(openaiApiKeyPropertyValue);
    }

    private static String normalizeText(String value) {
        return value == null ? "" : value;
    }
}
