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

import java.time.Instant;

/**
 * Ergebnis eines über {@link BatchRunTrigger#triggerRun()} ausgelösten
 * Verarbeitungslaufs.
 * <p>
 * Die sealed Hierarchie ermöglicht erschöpfendes Pattern-Matching:
 * <ul>
 *   <li>{@link Started} – Lauf wurde gestartet und ist abgeschlossen.</li>
 *   <li>{@link SkippedBusy} – Lauf wurde übersprungen, weil bereits ein
 *       Lauf aktiv war.</li>
 *   <li>{@link Failed} – Lauf ist mit einem technischen Fehler beendet.</li>
 * </ul>
 * <p>
 * {@link Throwable}-Instanzen werden nicht im Result-Objekt transportiert.
 * Stacktraces werden im Adapter geloggt; die GUI erhält ausschließlich
 * benutzerfreundliche deutsche Meldungen.
 */
public sealed interface BatchRunTriggerResult
        permits BatchRunTriggerResult.Started,
                BatchRunTriggerResult.SkippedBusy,
                BatchRunTriggerResult.Failed {

    /**
     * Der Lauf wurde erfolgreich gestartet und abgeschlossen.
     * <p>
     * Das Ergebnis enthält den Endzeitpunkt des Laufs sowie eine
     * {@link RunSummary} mit den aggregierten Verarbeitungszählern.
     * Ein No-op-Lauf (keine Kandidaten) ist ebenfalls {@code Started}
     * und liefert eine {@link RunSummary} mit allen Zählern gleich null.
     *
     * @param endedAt  Zeitpunkt, zu dem der Lauf abgeschlossen wurde
     * @param summary  Zusammenfassung der Verarbeitungsergebnisse
     */
    record Started(Instant endedAt, RunSummary summary)
            implements BatchRunTriggerResult {

        /**
         * Validiert, dass Pflichtfelder nicht null sind.
         */
        public Started {
            if (endedAt == null) {
                throw new IllegalArgumentException("endedAt darf nicht null sein");
            }
            if (summary == null) {
                throw new IllegalArgumentException("summary darf nicht null sein");
            }
        }
    }

    /**
     * Der Lauf wurde übersprungen, weil bereits ein anderer Lauf aktiv war.
     * <p>
     * {@link BatchRunTrigger#triggerRun()} kehrt sofort zurück, ohne
     * einen neuen Lauf zu starten. Dieser Zustand ist kein Fehler.
     */
    record SkippedBusy() implements BatchRunTriggerResult {}

    /**
     * Der Lauf ist mit einem technischen Fehler beendet worden.
     * <p>
     * Enthält eine benutzerlesbare deutsche Meldung für die GUI-Anzeige
     * sowie eine technische Meldung für Diagnose-Logging. Der zugehörige
     * Stacktrace wurde bereits im Adapter auf ERROR geloggt und wird hier
     * nicht transportiert.
     *
     * @param userMessage      deutsche, GUI-taugliche Fehlermeldung für den Endanwender
     * @param technicalMessage technische Detailmeldung für Diagnose und Logging
     */
    record Failed(String userMessage, String technicalMessage)
            implements BatchRunTriggerResult {

        /**
         * Validiert, dass Pflichtfelder nicht null sind.
         */
        public Failed {
            if (userMessage == null) {
                throw new IllegalArgumentException("userMessage darf nicht null sein");
            }
            if (technicalMessage == null) {
                throw new IllegalArgumentException("technicalMessage darf nicht null sein");
            }
        }
    }
}
