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

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatNullPointerException;

import java.time.Instant;
import java.util.List;

import org.junit.jupiter.api.Test;

/**
 * Tests für {@link TechnicalTestReport} und seine Helper-Methoden.
 */
class TechnicalTestReportTest {

    @Test
    void emptyReport_noErrors_noWarnings_noCorrectableFindings() {
        var report = new TechnicalTestReport(List.of(), Instant.now());
        assertThat(report.hasErrors()).isFalse();
        assertThat(report.hasWarnings()).isFalse();
        assertThat(report.hasCorrectableFindings()).isFalse();
        assertThat(report.size()).isZero();
    }

    @Test
    void report_withErrorFailure_hasErrors() {
        var failure = CheckpointResult.Failure.of(
                CheckpointId.TARGET_FOLDER_USABLE, CheckpointSeverity.ERROR, "Ordner fehlt");
        var report = new TechnicalTestReport(List.of(failure), Instant.now());
        assertThat(report.hasErrors()).isTrue();
        assertThat(report.hasWarnings()).isFalse();
    }

    @Test
    void report_withWarningFailure_hasWarnings() {
        var failure = CheckpointResult.Failure.of(
                CheckpointId.SELECTED_MODEL_PLAUSIBLE, CheckpointSeverity.WARNING, "Modell unbekannt");
        var report = new TechnicalTestReport(List.of(failure), Instant.now());
        assertThat(report.hasErrors()).isFalse();
        assertThat(report.hasWarnings()).isTrue();
    }

    @Test
    void report_withSuccessOnly_noErrorsNoWarnings() {
        var success = new CheckpointResult.Success(CheckpointId.SOURCE_FOLDER_PRESENT, "ok");
        var report = new TechnicalTestReport(List.of(success), Instant.now());
        assertThat(report.hasErrors()).isFalse();
        assertThat(report.hasWarnings()).isFalse();
        assertThat(report.hasCorrectableFindings()).isFalse();
    }

    @Test
    void report_withCorrectableFailure_hasCorrectableFindings() {
        var suggestion = new CorrectionSuggestion.CreateDirectory("/path/target", "Zielordner anlegen");
        var failure = CheckpointResult.Failure.withCorrection(
                CheckpointId.TARGET_FOLDER_USABLE, CheckpointSeverity.ERROR, "Ordner fehlt", suggestion);
        var report = new TechnicalTestReport(List.of(failure), Instant.now());
        assertThat(report.hasCorrectableFindings()).isTrue();
    }

    @Test
    void deriveCorrectionPlan_extractsSuggestionsFromFailures() {
        var suggestion1 = new CorrectionSuggestion.CreateDirectory("/path/target", "Zielordner anlegen");
        var suggestion2 = new CorrectionSuggestion.CreatePromptFile("/path/prompt.txt", "Prompt-Datei erzeugen", 60);
        var failure1 = CheckpointResult.Failure.withCorrection(
                CheckpointId.TARGET_FOLDER_USABLE, CheckpointSeverity.ERROR, "fehlt", suggestion1);
        var failure2 = CheckpointResult.Failure.withCorrection(
                CheckpointId.PROMPT_FILE_PRESENT, CheckpointSeverity.ERROR, "fehlt", suggestion2);
        var success = new CheckpointResult.Success(CheckpointId.SOURCE_FOLDER_PRESENT, "ok");

        var report = new TechnicalTestReport(List.of(failure1, success, failure2), Instant.now());
        var plan = report.deriveCorrectionPlan();

        assertThat(plan.hasCorrections()).isTrue();
        assertThat(plan.size()).isEqualTo(2);
        assertThat(plan.suggestions()).containsExactly(suggestion1, suggestion2);
    }

    @Test
    void deriveCorrectionPlan_emptyWhenNoCorrectableFailures() {
        var failure = CheckpointResult.Failure.of(
                CheckpointId.API_KEY_ACCEPTED, CheckpointSeverity.ERROR, "Schlüssel falsch");
        var report = new TechnicalTestReport(List.of(failure), Instant.now());
        var plan = report.deriveCorrectionPlan();
        assertThat(plan.hasCorrections()).isFalse();
    }

    @Test
    void resultsListIsImmutable() {
        var mutable = new java.util.ArrayList<CheckpointResult>();
        mutable.add(new CheckpointResult.Success(CheckpointId.CONFIGURATION_BASIC_VALIDATION, "ok"));
        var report = new TechnicalTestReport(mutable, Instant.now());
        mutable.add(new CheckpointResult.Success(CheckpointId.SOURCE_FOLDER_PRESENT, "ok2"));
        assertThat(report.results()).hasSize(1);
    }

    @Test
    void nullResultsThrows() {
        assertThatNullPointerException()
                .isThrownBy(() -> new TechnicalTestReport(null, Instant.now()));
    }

    @Test
    void nullEvaluatedAtThrows() {
        assertThatNullPointerException()
                .isThrownBy(() -> new TechnicalTestReport(List.of(), null));
    }
}
