package de.gecheckt.pdf.umbenenner.application.usecase;

import java.util.Objects;

import de.gecheckt.pdf.umbenenner.application.port.out.PromptLoadingFailure;
import de.gecheckt.pdf.umbenenner.application.port.out.PromptLoadingResult;
import de.gecheckt.pdf.umbenenner.application.port.out.PromptLoadingSuccess;
import de.gecheckt.pdf.umbenenner.application.port.out.PromptPort;
import de.gecheckt.pdf.umbenenner.application.port.out.PromptSaveResult;
import de.gecheckt.pdf.umbenenner.application.validation.technicaltest.CorrectionOutcome;
import de.gecheckt.pdf.umbenenner.application.validation.technicaltest.CorrectionSuggestion;
import de.gecheckt.pdf.umbenenner.application.validation.technicaltest.ResourceCreationPort;

/**
 * Use-Case zur Anzeige und Bearbeitung des KI-Prompt-Templates über die GUI.
 * <p>
 * Dieser Use-Case vermittelt zwischen dem GUI-Adapter und dem {@link PromptPort} sowie dem
 * {@link ResourceCreationPort}. Er kennt keine JavaFX-Typen, kein Dateisystem und keine
 * HTTP-Kommunikation; alle technischen Details bleiben in den jeweiligen Adaptern.
 * <p>
 * <strong>Verantwortung:</strong>
 * <ul>
 *   <li>Aktuellen Prompt-Inhalt laden und als strukturiertes Ergebnis zurückgeben.</li>
 *   <li>Bearbeiteten Inhalt atomar in die konfigurierte Prompt-Datei speichern.</li>
 *   <li>Anlegen einer Standard-Prompt-Datei delegieren, wenn keine Datei vorhanden ist.</li>
 * </ul>
 * <p>
 * <strong>Abgrenzung:</strong> Dieser Use-Case trifft keine Entscheidungen über
 * Benutzeroberfläche, Threading oder Dirty-State-Verwaltung. Diese Verantwortung
 * liegt im GUI-Adapter.
 */
public class DefaultPromptEditorUseCase {

    private final PromptPort promptPort;
    private final ResourceCreationPort resourceCreationPort;

    /**
     * Erstellt den Use-Case mit den erforderlichen Ports.
     *
     * @param promptPort             Port zum Laden und Speichern des Prompt-Templates;
     *                               darf nicht {@code null} sein
     * @param resourceCreationPort   Port zum Anlegen der Standard-Prompt-Datei;
     *                               darf nicht {@code null} sein
     * @throws NullPointerException wenn ein Parameter {@code null} ist
     */
    public DefaultPromptEditorUseCase(PromptPort promptPort, ResourceCreationPort resourceCreationPort) {
        this.promptPort = Objects.requireNonNull(promptPort, "promptPort must not be null");
        this.resourceCreationPort = Objects.requireNonNull(resourceCreationPort,
                "resourceCreationPort must not be null");
    }

    /**
     * Lädt den aktuellen Prompt-Inhalt aus der konfigurierten Prompt-Datei.
     * <p>
     * Delegiert direkt an {@link PromptPort#loadPrompt()} und gibt das Ergebnis
     * unverändert zurück.
     *
     * @return {@link PromptLoadingResult} mit Inhalt und Identifikator bei Erfolg,
     *         oder einem klassifizierten Fehler; nie {@code null}
     * @see PromptLoadingSuccess
     * @see PromptLoadingFailure
     */
    public PromptLoadingResult loadPrompt() {
        return promptPort.loadPrompt();
    }

    /**
     * Speichert den übergebenen Inhalt atomar in die konfigurierte Prompt-Datei.
     * <p>
     * Delegiert direkt an {@link PromptPort#savePrompt(String)}. Der Zielpfad ist
     * Implementierungsdetail des Adapters.
     *
     * @param content der zu speichernde Prompt-Inhalt; darf nicht {@code null} sein
     * @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
     */
    public PromptSaveResult savePrompt(String content) {
        Objects.requireNonNull(content, "content must not be null");
        return promptPort.savePrompt(content);
    }

    /**
     * Legt eine Standard-Prompt-Datei an, wenn noch keine vorhanden ist.
     * <p>
     * Delegiert an {@link ResourceCreationPort#createPromptFile(CorrectionSuggestion.CreatePromptFile)}.
     * Das Ergebnis beschreibt, ob die Datei angelegt wurde, ob sie bereits existierte
     * oder ob ein Fehler aufgetreten ist.
     *
     * @param suggestion Korrekturvorschlag mit dem Zielpfad; darf nicht {@code null} sein
     * @return {@link CorrectionOutcome} mit dem Ergebnis der Aktion; nie {@code null}
     * @throws NullPointerException wenn {@code suggestion} null ist
     */
    public CorrectionOutcome createDefaultPromptIfMissing(CorrectionSuggestion.CreatePromptFile suggestion) {
        Objects.requireNonNull(suggestion, "suggestion must not be null");
        return resourceCreationPort.createPromptFile(suggestion);
    }
}
