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

import java.util.List;
import java.util.Objects;

/**
 * Gesamtergebnis der Ausführung eines bestätigten {@link CorrectionPlan}.
 * <p>
 * Enthält für jeden im Plan enthaltenen Korrekturvorschlag ein {@link CorrectionOutcome}.
 * Die Reihenfolge der Ergebnisse entspricht der Reihenfolge der Vorschläge im Plan.
 * <p>
 * Dieser Record ist immutable und enthält keine JavaFX-Typen.
 *
 * @param outcomes  Ergebnisliste in Ausführungsreihenfolge; nie {@code null}
 */
public record CorrectionExecutionReport(List<CorrectionOutcome> outcomes) {

    /**
     * Erstellt einen neuen Ausführungsbericht.
     *
     * @param outcomes  Liste der Ausführungsergebnisse; darf nicht {@code null} sein
     * @throws NullPointerException wenn {@code outcomes} {@code null} ist
     */
    public CorrectionExecutionReport {
        Objects.requireNonNull(outcomes, "outcomes must not be null");
        outcomes = List.copyOf(outcomes);
    }

    /**
     * Gibt an, ob alle Korrekturen erfolgreich angewendet wurden.
     * <p>
     * Gibt {@code true} zurück, wenn alle Ergebnisse vom Typ {@link CorrectionOutcome.Applied}
     * sind und der Bericht mindestens einen Eintrag enthält.
     *
     * @return {@code true} wenn mindestens ein Eintrag vorhanden ist und alle angewendet wurden
     */
    public boolean allApplied() {
        return !outcomes.isEmpty()
                && outcomes.stream().allMatch(o -> o instanceof CorrectionOutcome.Applied);
    }

    /**
     * Gibt an, ob mindestens eine Korrektur gescheitert ist.
     *
     * @return {@code true} wenn mindestens ein {@link CorrectionOutcome.Failed} vorliegt
     */
    public boolean hasFailures() {
        return outcomes.stream().anyMatch(o -> o instanceof CorrectionOutcome.Failed);
    }

    /**
     * Gibt an, ob mindestens eine Korrektur nicht versucht wurde.
     *
     * @return {@code true} wenn mindestens ein {@link CorrectionOutcome.NotAttempted} vorliegt
     */
    public boolean hasNotAttempted() {
        return outcomes.stream().anyMatch(o -> o instanceof CorrectionOutcome.NotAttempted);
    }

    /**
     * Gibt die Gesamtzahl der Ergebnisse zurück.
     *
     * @return Anzahl der Ergebnisse; nie negativ
     */
    public int size() {
        return outcomes.size();
    }
}
