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

/**
 * Outbound-Port zum Laden und Speichern des externen Prompt-Templates.
 * <p>
 * Dieses Interface abstrahiert den Zugriff auf die Prompt-Datei und erlaubt der
 * Application-Schicht, unabhängig vom konkreten Speichermedium zu bleiben.
 * <p>
 * <strong>Designprinzipien:</strong>
 * <ul>
 *   <li>Der Prompt wird nicht im Code fest verdrahtet, sondern aus einer externen Quelle geladen.</li>
 *   <li>Jeder Prompt erhält einen stabilen Identifikator für die lückenlose Nachvollziehbarkeit.</li>
 *   <li>Ergebnisse werden als strukturierte Typen zurückgegeben, niemals als Exceptions.</li>
 *   <li>Der Pfad zur Prompt-Datei ist Implementierungsdetail des Adapters – er erscheint nicht
 *       in der Port-Signatur (hexagonale Regel: keine {@code Path}/{@code File}-Typen).</li>
 * </ul>
 * <p>
 * <strong>Adapter-Verantwortung:</strong>
 * <ul>
 *   <li>Prompt-Datei lokalisieren und lesen.</li>
 *   <li>Stabilen Identifikator ableiten (z. B. Dateiname).</li>
 *   <li>Leere oder technisch unbrauchbare Prompts ablehnen.</li>
 *   <li>Beim Speichern: atomares Schreiben via temporäre Datei und {@code ATOMIC_MOVE}.</li>
 *   <li>Alle Datei-I/O-, Ressourcen- und Konfigurationsdetails kapseln.</li>
 * </ul>
 * <p>
 * <strong>Nicht-Ziele dieses Ports:</strong>
 * <ul>
 *   <li>Prompt-Parsing oder Template-Verarbeitung</li>
 *   <li>Kombination von Prompt und Dokumenttext (Application-Schicht)</li>
 *   <li>Validierung des Prompt-Inhalts gegen Domänenregeln</li>
 * </ul>
 */
public interface PromptPort {

    /**
     * Lädt das konfigurierte externe Prompt-Template.
     * <p>
     * Diese Methode wird einmal pro Verarbeitungslauf aufgerufen, um den aktuellen Prompt zu laden.
     * Inhalt und stabiler Identifikator werden gemeinsam zurückgegeben.
     * <p>
     * Bei einem technischen Fehler (Datei nicht gefunden, I/O-Fehler, leerer Inhalt) wird
     * {@link PromptLoadingFailure} zurückgegeben – keine Exception wird geworfen.
     *
     * @return {@link PromptLoadingResult} mit Erfolg oder klassifiziertem Fehler; nie {@code null}
     * @see PromptLoadingSuccess
     * @see PromptLoadingFailure
     */
    PromptLoadingResult loadPrompt();

    /**
     * Speichert den übergebenen Inhalt atomar in die konfigurierte Prompt-Datei.
     * <p>
     * Der Zielpfad wird intern aus der Konfiguration des Adapters ermittelt und ist
     * <em>nicht</em> Teil dieser Signatur (hexagonale Regel: keine {@code Path}/{@code File}-Typen
     * im Port-Vertrag).
     * <p>
     * Die Implementierung schreibt zunächst in eine temporäre Datei <em>im selben Verzeichnis</em>
     * wie die Zieldatei und verschiebt diese danach atomar via {@code ATOMIC_MOVE}.
     * Bei einem Fehler beim atomaren Verschieben wird <strong>kein stiller Fallback</strong>
     * auf ein nicht-atomares Schreiben durchgeführt; stattdessen wird
     * {@link PromptSaveResult.AtomicMoveFailed} zurückgegeben.
     * <p>
     * Zeichenkodierung: UTF-8. Zeilenenden werden unverändert übernommen.
     *
     * @param content der zu speichernde Prompt-Inhalt; darf leer sein (Entscheidung liegt
     *                beim Aufrufer, ob ein leerer Prompt erwünscht ist)
     * @return {@link PromptSaveResult} mit Erfolg oder klassifiziertem Fehler; nie {@code null}
     * @throws NullPointerException wenn {@code content} null ist
     * @see PromptSaveResult.Saved
     * @see PromptSaveResult.WriteFailed
     * @see PromptSaveResult.TargetDirectoryMissing
     * @see PromptSaveResult.AtomicMoveFailed
     */
    PromptSaveResult savePrompt(String content);
}
