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

import java.util.Objects;

/**
 * Versiegelter Korrekturvorschlag für eine schreibende technische Korrekturmaßnahme.
 * <p>
 * Korrekturvorschläge beschreiben <em>was</em> korrigiert werden soll, aber noch nicht
 * <em>wie</em>. Die konkrete Ausführung übernimmt der {@link ResourceCreationPort}. Ein
 * Vorschlag wird dem Benutzer vor der Ausführung in einem gesammelten Bestätigungsdialog
 * angezeigt; ohne Bestätigung wird keine schreibende Änderung vorgenommen.
 * <p>
 * Nicht automatisch korrigierbare Probleme (falscher API-Key, unerreichbare Base-URL,
 * nicht verfügbare Modellliste) werden niemals als {@code CorrectionSuggestion} modelliert.
 * <p>
 * Alle Pfade werden als {@code String} übergeben, analog zur Konvention der übrigen
 * Outbound-Ports dieses Projekts. Der Adapter-Out ist für die Konvertierung in
 * {@code java.nio.file.Path} zuständig.
 */
public sealed interface CorrectionSuggestion
        permits CorrectionSuggestion.CreateDirectory,
                CorrectionSuggestion.CreatePromptFile,
                CorrectionSuggestion.PrepareSqlitePath {
    String PATH_NOT_NULL = "path must not be null";
    String DESCRIPTION_NOT_NULL = "descriptionForUser must not be null";


    /**
     * Gibt eine kurze deutsche Beschreibung der vorgeschlagenen Korrektur zurück,
     * die dem Benutzer im Bestätigungsdialog angezeigt wird.
     *
     * @return deutsche Beschreibung; nie {@code null}
     */
    String descriptionForUser();

    /**
     * Ein fehlender Ordner soll angelegt werden.
     * <p>
     * Anwendungsfälle: fehlender Zielordner.
     * Es werden nur Ordner angelegt, die noch nicht existieren und deren Elternpfad
     * erreichbar ist.
     *
     * @param path            Pfad des anzulegenden Ordners als String; nie {@code null}
     * @param descriptionForUser  deutsche Beschreibung für den Bestätigungsdialog; nie {@code null}
     */
    record CreateDirectory(
            String path,
            String descriptionForUser) implements CorrectionSuggestion {

        /**
         * Erstellt einen Vorschlag zum Anlegen eines Ordners.
         *
         * @param path               Pfad des Ordners; darf nicht {@code null} oder leer sein
         * @param descriptionForUser deutsche Beschreibung; darf nicht {@code null} sein
         * @throws NullPointerException     wenn ein Parameter {@code null} ist
         * @throws IllegalArgumentException wenn {@code path} leer ist
         */
        public CreateDirectory {
            Objects.requireNonNull(path, PATH_NOT_NULL);
            Objects.requireNonNull(descriptionForUser, DESCRIPTION_NOT_NULL);
            if (path.isBlank()) {
                throw new IllegalArgumentException("path must not be blank");
            }
        }
    }

    /**
     * Eine fehlende Prompt-Datei soll mit einem deutschen Standardinhalt erzeugt werden.
     * <p>
     * Die Erzeugung erfolgt nur, wenn der Zielpfad beschreibbar ist. Der konkrete
     * Standardinhalt wird vom {@link ResourceCreationPort} bereitgestellt. Der
     * Standardpfad liegt im selben Ordner wie die {@code .properties}-Datei.
     * <p>
     * Der {@code maxTitleLength} wird vom Adapter als Platzhalterwert in den erzeugten
     * Standardinhalt eingesetzt, damit der erzeugte Standard-Prompt inhaltlich zu der
     * konfigurierten maximalen Titellänge passt.
     *
     * @param path               Pfad der anzulegenden Prompt-Datei als String; nie {@code null}
     * @param descriptionForUser deutsche Beschreibung für den Bestätigungsdialog; nie {@code null}
     * @param maxTitleLength     konfigurierte maximale Titellänge, die im erzeugten
     *                           Standardinhalt verwendet wird; muss {@code >= 1} sein
     */
    record CreatePromptFile(
            String path,
            String descriptionForUser,
            int maxTitleLength) implements CorrectionSuggestion {

        /**
         * Erstellt einen Vorschlag zum Erzeugen einer deutschen Standard-Prompt-Datei.
         *
         * @param path               Pfad der Prompt-Datei; darf nicht {@code null} oder leer sein
         * @param descriptionForUser deutsche Beschreibung; darf nicht {@code null} sein
         * @param maxTitleLength     konfigurierte maximale Titellänge; muss {@code >= 1} sein
         * @throws NullPointerException     wenn {@code path} oder {@code descriptionForUser} {@code null} ist
         * @throws IllegalArgumentException wenn {@code path} leer ist oder
         *                                  {@code maxTitleLength < 1}
         */
        public CreatePromptFile {
            Objects.requireNonNull(path, PATH_NOT_NULL);
            Objects.requireNonNull(descriptionForUser, DESCRIPTION_NOT_NULL);
            if (path.isBlank()) {
                throw new IllegalArgumentException("path must not be blank");
            }
            if (maxTitleLength < 1) {
                throw new IllegalArgumentException(
                        "maxTitleLength must be >= 1, got: " + maxTitleLength);
            }
        }
    }

    /**
     * Ein fehlender oder noch nicht vorbereiteter SQLite-Pfad soll nutzbar gemacht werden.
     * <p>
     * Konkret bedeutet das: Falls die SQLite-Datei noch nicht existiert, aber ihr
     * übergeordneter Ordner vorhanden oder anlegbar ist, wird der Ordner sichergestellt.
     * Eine leere SQLite-Datei wird nicht manuell erzeugt; das übernimmt das JDBC-Layer
     * beim ersten Datenbankzugriff.
     *
     * @param path               Pfad der SQLite-Datei als String; nie {@code null}
     * @param descriptionForUser deutsche Beschreibung für den Bestätigungsdialog; nie {@code null}
     */
    record PrepareSqlitePath(
            String path,
            String descriptionForUser) implements CorrectionSuggestion {

        /**
         * Erstellt einen Vorschlag zur Vorbereitung des SQLite-Pfads.
         *
         * @param path               Pfad der SQLite-Datei; darf nicht {@code null} oder leer sein
         * @param descriptionForUser deutsche Beschreibung; darf nicht {@code null} sein
         * @throws NullPointerException     wenn ein Parameter {@code null} ist
         * @throws IllegalArgumentException wenn {@code path} leer ist
         */
        public PrepareSqlitePath {
            Objects.requireNonNull(path, PATH_NOT_NULL);
            Objects.requireNonNull(descriptionForUser, DESCRIPTION_NOT_NULL);
            if (path.isBlank()) {
                throw new IllegalArgumentException("path must not be blank");
            }
        }
    }
}
