package de.gecheckt.pdf.umbenenner.application.port.out;

/**
 * Versiegeltes Ergebnis-Interface für das Speichern einer Prompt-Datei via
 * {@link PromptPort#savePrompt(String)}.
 * <p>
 * Mögliche Ergebnisse:
 * <ul>
 *   <li>{@link Saved} – das Speichern war erfolgreich.</li>
 *   <li>{@link WriteFailed} – ein technischer Fehler beim Schreiben ist aufgetreten.</li>
 *   <li>{@link TargetDirectoryMissing} – der konfigurierte Zielordner existiert nicht.</li>
 *   <li>{@link AtomicMoveFailed} – das atomare Verschieben der temporären Datei ist
 *       fehlgeschlagen; kein stiller Fallback.</li>
 * </ul>
 */
public sealed interface PromptSaveResult
        permits PromptSaveResult.Saved,
                PromptSaveResult.WriteFailed,
                PromptSaveResult.TargetDirectoryMissing,
                PromptSaveResult.AtomicMoveFailed {
    String MESSAGE_NOT_NULL = "message must not be null";


    /**
     * Die Prompt-Datei wurde erfolgreich gespeichert.
     *
     * @param absolutePath absoluter Pfad der gespeicherten Datei; nie {@code null}
     */
    record Saved(String absolutePath) implements PromptSaveResult {

        /**
         * Erstellt ein Saved-Ergebnis.
         *
         * @param absolutePath absoluter Pfad der gespeicherten Datei; darf nicht {@code null} sein
         * @throws NullPointerException wenn {@code absolutePath} null ist
         */
        public Saved {
            java.util.Objects.requireNonNull(absolutePath, "absolutePath must not be null");
        }
    }

    /**
     * Das Schreiben der temporären Datei ist fehlgeschlagen.
     *
     * @param message  Fehlerbeschreibung; nie {@code null}
     * @param cause    auslösende Ausnahme; kann {@code null} sein
     */
    record WriteFailed(String message, Throwable cause) implements PromptSaveResult {

        /**
         * Erstellt ein WriteFailed-Ergebnis.
         *
         * @param message Fehlerbeschreibung; darf nicht {@code null} sein
         * @param cause   auslösende Ausnahme; kann {@code null} sein
         * @throws NullPointerException wenn {@code message} null ist
         */
        public WriteFailed {
            java.util.Objects.requireNonNull(message, MESSAGE_NOT_NULL);
        }
    }

    /**
     * Der konfigurierte Zielordner existiert nicht.
     *
     * @param message Beschreibung des fehlenden Ordners; nie {@code null}
     */
    record TargetDirectoryMissing(String message) implements PromptSaveResult {

        /**
         * Erstellt ein TargetDirectoryMissing-Ergebnis.
         *
         * @param message Beschreibung des fehlenden Ordners; darf nicht {@code null} sein
         * @throws NullPointerException wenn {@code message} null ist
         */
        public TargetDirectoryMissing {
            java.util.Objects.requireNonNull(message, MESSAGE_NOT_NULL);
        }
    }

    /**
     * Das atomare Verschieben der temporären Datei zur Zieldatei ist fehlgeschlagen.
     * Es wird kein stiller Fallback auf nicht-atomares Schreiben durchgeführt.
     *
     * @param message Fehlerbeschreibung; nie {@code null}
     */
    record AtomicMoveFailed(String message) implements PromptSaveResult {

        /**
         * Erstellt ein AtomicMoveFailed-Ergebnis.
         *
         * @param message Fehlerbeschreibung; darf nicht {@code null} sein
         * @throws NullPointerException wenn {@code message} null ist
         */
        public AtomicMoveFailed {
            java.util.Objects.requireNonNull(message, MESSAGE_NOT_NULL);
        }
    }
}
