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

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

import org.junit.jupiter.api.Test;

/**
 * Tests für das versiegelte Interface {@link CorrectionSuggestion} und seine Untertypen.
 */
class CorrectionSuggestionTest {

    // --- CreateDirectory ---

    @Test
    void createDirectory_storesPathAndDescription() {
        var s = new CorrectionSuggestion.CreateDirectory("/path/to/dir", "Ordner anlegen");
        assertThat(s.path()).isEqualTo("/path/to/dir");
        assertThat(s.descriptionForUser()).isEqualTo("Ordner anlegen");
    }

    @Test
    void createDirectory_blankPathThrows() {
        assertThatIllegalArgumentException()
                .isThrownBy(() -> new CorrectionSuggestion.CreateDirectory("  ", "desc"));
    }

    @Test
    void createDirectory_nullPathThrows() {
        assertThatNullPointerException()
                .isThrownBy(() -> new CorrectionSuggestion.CreateDirectory(null, "desc"));
    }

    // --- CreatePromptFile ---

    @Test
    void createPromptFile_storesPathAndDescription() {
        var s = new CorrectionSuggestion.CreatePromptFile("/config/prompt.txt", "Prompt-Datei erzeugen", 60);
        assertThat(s.path()).isEqualTo("/config/prompt.txt");
        assertThat(s.descriptionForUser()).isEqualTo("Prompt-Datei erzeugen");
        assertThat(s.maxTitleLength()).isEqualTo(60);
    }

    @Test
    void createPromptFile_blankPathThrows() {
        assertThatIllegalArgumentException()
                .isThrownBy(() -> new CorrectionSuggestion.CreatePromptFile("", "desc", 60));
    }

    @Test
    void createPromptFile_zeroMaxTitleLengthThrows() {
        assertThatIllegalArgumentException()
                .isThrownBy(() -> new CorrectionSuggestion.CreatePromptFile("/p", "desc", 0));
    }

    // --- PrepareSqlitePath ---

    @Test
    void prepareSqlitePath_storesPathAndDescription() {
        var s = new CorrectionSuggestion.PrepareSqlitePath("/data/store.db", "SQLite-Pfad vorbereiten");
        assertThat(s.path()).isEqualTo("/data/store.db");
        assertThat(s.descriptionForUser()).isEqualTo("SQLite-Pfad vorbereiten");
    }

    @Test
    void prepareSqlitePath_nullDescriptionThrows() {
        assertThatNullPointerException()
                .isThrownBy(() -> new CorrectionSuggestion.PrepareSqlitePath("/path", null));
    }

    // --- Pattern Matching ---

    @Test
    void patternMatching_coversAllPermittedTypes() {
        CorrectionSuggestion dir = new CorrectionSuggestion.CreateDirectory("/a", "d1");
        CorrectionSuggestion prompt = new CorrectionSuggestion.CreatePromptFile("/b", "d2", 60);
        CorrectionSuggestion sqlite = new CorrectionSuggestion.PrepareSqlitePath("/c", "d3");

        assertThat(classify(dir)).isEqualTo("directory");
        assertThat(classify(prompt)).isEqualTo("promptFile");
        assertThat(classify(sqlite)).isEqualTo("sqlitePath");
    }

    private String classify(CorrectionSuggestion s) {
        return switch (s) {
            case CorrectionSuggestion.CreateDirectory d -> "directory";
            case CorrectionSuggestion.CreatePromptFile p -> "promptFile";
            case CorrectionSuggestion.PrepareSqlitePath sp -> "sqlitePath";
        };
    }
}
