package de.gecheckt.pdf.umbenenner.adapter.in.gui.batchrun;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.Test;

/**
 * Unit-Tests für {@link AiFailureMessageTranslator}.
 * <p>
 * Prüft alle definierten Mapping-Fälle sowie Randbedingungen wie
 * {@code null}-Eingaben und unbekannte Fehlertexte. Die zurückgegebenen Meldungen
 * dürfen keinen Verweis auf interne Logdateien enthalten.
 */
class AiFailureMessageTranslatorTest {

    // -------------------------------------------------------------------------
    // Pre-Check-Fehler: kein lesbarer Text
    // -------------------------------------------------------------------------

    @Test
    void noUsableText_liefertLesbarkeitsMeldung() {
        String result = AiFailureMessageTranslator.translate(
                "Processing failed (retryable). Reason: No usable text in extracted PDF content");
        assertTrue(result.contains("keinen lesbaren Text"), result);
        assertTrue(result.contains("OCR"), result);
    }

    @Test
    void noUsableText_grossKleinschreibung_wirdErkannt() {
        String result = AiFailureMessageTranslator.translate("NO USABLE TEXT found");
        assertTrue(result.contains("keinen lesbaren Text"), result);
    }

    // -------------------------------------------------------------------------
    // KI-Validierungsfehler: Titel zu lang
    // -------------------------------------------------------------------------

    @Test
    void titleExceeds_liefertTitelZuLangMeldung() {
        String result = AiFailureMessageTranslator.translate(
                "Processing failed finally (not retryable). AI functional error: "
                        + "Title exceeds 60 characters (base title): 'Sehr langer Titel der das Limit ueberschreitet'");
        assertTrue(result.contains("ist zu lang"), result);
        assertTrue(result.contains("Sehr langer Titel der das Limit ueberschreitet"), result);
        assertTrue(result.contains("Limit: 60"), result);
        assertTrue(result.contains("manuell kürzen"), result);
    }

    @Test
    void titleExceeds_mitTitellaengeInMeldung() {
        String result = AiFailureMessageTranslator.translate(
                "Title exceeds 60 characters (base title): 'Ein langer Dokumenttitel'");
        assertTrue(result.contains("Ein langer Dokumenttitel"), result);
        assertTrue(result.contains("Limit: 60"), result);
    }

    @Test
    void titleExceeds_ohneParsebaresFormat_liefertGenerischenHinweis() {
        String result = AiFailureMessageTranslator.translate("title exceeds some limit");
        assertTrue(result.contains("Titel"), result);
        assertTrue(result.contains("manuell kürzen"), result);
    }

    // -------------------------------------------------------------------------
    // Defekte oder strukturell nicht lesbare PDF-Datei
    // -------------------------------------------------------------------------

    @Test
    void contentNotExtractable_liefertDefektePdfMeldung() {
        String result = AiFailureMessageTranslator.translate(
                "Processing failed (retryable). Reason: PDF content not extractable");
        assertTrue(result.contains("ungültig oder beschädigt"), result);
    }

    @Test
    void ioException_liefertDefektePdfMeldung() {
        String result = AiFailureMessageTranslator.translate(
                "Processing failed (retryable). Technical: IOException reading file: test.pdf");
        assertTrue(result.contains("ungültig oder beschädigt"), result);
    }

    @Test
    void endOfFile_liefertDefektePdfMeldung() {
        String result = AiFailureMessageTranslator.translate(
                "Processing failed (retryable). Technical: Unexpected end of file");
        assertTrue(result.contains("ungültig oder beschädigt"), result);
    }

    @Test
    void eof_liefertDefektePdfMeldung() {
        String result = AiFailureMessageTranslator.translate(
                "Technical error: EOF while reading PDF structure");
        assertTrue(result.contains("ungültig oder beschädigt"), result);
    }

    // -------------------------------------------------------------------------
    // HTTP-Statuscodes
    // -------------------------------------------------------------------------

    @Test
    void http401_liefertApiSchluesselMeldung() {
        String result = AiFailureMessageTranslator.translate(
                "Processing failed (retryable). AI technical error: AI invocation failed [HTTP_401]: AI service returned status 401");
        assertEquals("KI-Dienst: Ungültiger API-Schlüssel. Bitte in den Einstellungen prüfen.", result);
    }

    @Test
    void http401_kleinschreibung_wirdErkannt() {
        String result = AiFailureMessageTranslator.translate("http_401 ungültig");
        assertEquals("KI-Dienst: Ungültiger API-Schlüssel. Bitte in den Einstellungen prüfen.", result);
    }

    @Test
    void http403_liefertZugriffVerweigertMeldung() {
        String result = AiFailureMessageTranslator.translate("HTTP_403 Forbidden");
        assertEquals("KI-Dienst: Zugriff verweigert. Bitte API-Schlüssel und Berechtigungen prüfen.", result);
    }

    @Test
    void http429_liefertRateLimitMeldung() {
        String result = AiFailureMessageTranslator.translate("AI invocation failed [HTTP_429]: rate limit");
        assertEquals("KI-Dienst: Anfragelimit erreicht. Bitte später erneut versuchen.", result);
    }

    @Test
    void http500_liefertServerFehlerMeldung() {
        String result = AiFailureMessageTranslator.translate("AI invocation failed [HTTP_500]: internal error");
        assertEquals("KI-Dienst vorübergehend nicht erreichbar. Bitte später erneut versuchen.", result);
    }

    @Test
    void http503_liefertServerFehlerMeldung() {
        String result = AiFailureMessageTranslator.translate("HTTP_503 Service Unavailable");
        assertEquals("KI-Dienst vorübergehend nicht erreichbar. Bitte später erneut versuchen.", result);
    }

    // -------------------------------------------------------------------------
    // Netzwerk- und Verbindungsfehler
    // -------------------------------------------------------------------------

    @Test
    void connectionFehler_liefertVerbindungsMeldung() {
        String result = AiFailureMessageTranslator.translate("Connection refused to https://api.example.com");
        assertEquals("KI-Dienst nicht erreichbar. Bitte Verbindung und Konfiguration prüfen.", result);
    }

    @Test
    void timeoutFehler_liefertVerbindungsMeldung() {
        String result = AiFailureMessageTranslator.translate("AI technical error: timeout after 30s");
        assertEquals("KI-Dienst nicht erreichbar. Bitte Verbindung und Konfiguration prüfen.", result);
    }

    @Test
    void refusedFehler_liefertVerbindungsMeldung() {
        String result = AiFailureMessageTranslator.translate("connect refused");
        assertEquals("KI-Dienst nicht erreichbar. Bitte Verbindung und Konfiguration prüfen.", result);
    }

    // -------------------------------------------------------------------------
    // Unbekannter Fehler (Fallback)
    // -------------------------------------------------------------------------

    @Test
    void unbekannterFehler_haengtTechnischeMeldungAn() {
        String result = AiFailureMessageTranslator.translate("some completely unknown error text");
        assertEquals("Verarbeitung fehlgeschlagen. Technischer Grund: some completely unknown error text",
                result);
    }

    // -------------------------------------------------------------------------
    // KI-Antwort strukturell nicht verwertbar (JSON/Parse)
    // -------------------------------------------------------------------------

    @Test
    void notJsonObject_liefertFormatMeldung() {
        String result = AiFailureMessageTranslator.translate(
                "AI response could not be parsed [NOT_JSON_OBJECT]: AI response is not a pure JSON object"
                        + " (contains extra text or is not an object)");
        assertTrue(result.contains("nicht im erwarteten Format"), result);
        assertTrue(result.contains("JSON"), result);
    }

    @Test
    void invalidJson_liefertFormatMeldung() {
        String result = AiFailureMessageTranslator.translate(
                "AI response could not be parsed [INVALID_JSON]: AI response is not valid JSON: ...");
        assertTrue(result.contains("nicht im erwarteten Format"), result);
    }

    @Test
    void null_liefertFallback() {
        String result = AiFailureMessageTranslator.translate(null);
        assertEquals("Verarbeitung fehlgeschlagen. Bitte Konfiguration prüfen und ggf. erneut verarbeiten.", result);
    }

    @Test
    void leerstring_liefertFallback() {
        String result = AiFailureMessageTranslator.translate("");
        assertEquals("Verarbeitung fehlgeschlagen. Bitte Konfiguration prüfen und ggf. erneut verarbeiten.", result);
    }

    @Test
    void nurLeerzeichen_liefertFallback() {
        String result = AiFailureMessageTranslator.translate("   ");
        assertEquals("Verarbeitung fehlgeschlagen. Bitte Konfiguration prüfen und ggf. erneut verarbeiten.", result);
    }

    // -------------------------------------------------------------------------
    // Qualitätsregeln: kein Verweis auf interne Logs
    // -------------------------------------------------------------------------

    @Test
    void keineMeldungEnthältAnwendungslogVerweis() {
        String[] eingaben = {
            null, "", "  ", "HTTP_401", "HTTP_403", "HTTP_429", "HTTP_500",
            "connection error", "timeout", "refused", "unbekannt",
            "no usable text", "content not extractable", "IOException",
            "Title exceeds 60 characters (base title): 'Titel'"
        };
        for (String eingabe : eingaben) {
            String result = AiFailureMessageTranslator.translate(eingabe);
            assertFalse(result.toLowerCase().contains("anwendungslog"),
                    "Meldung darf keinen Anwendungslog-Verweis enthalten für: " + eingabe);
        }
    }

    @Test
    void alleEingaben_liefernNichtLeereTexte() {
        String[] eingaben = {
            null, "", "  ", "HTTP_401", "HTTP_403", "HTTP_429", "HTTP_500",
            "connection error", "timeout", "refused", "unbekannt"
        };
        for (String eingabe : eingaben) {
            String result = AiFailureMessageTranslator.translate(eingabe);
            assertNotNull(result, "Ergebnis darf nicht null sein für: " + eingabe);
            assertFalse(result.isBlank(), "Ergebnis darf nicht leer sein für: " + eingabe);
        }
    }

    // -------------------------------------------------------------------------
    // Reihenfolge: HTTP_401 hat Vorrang vor HTTP_5xx
    // -------------------------------------------------------------------------

    @Test
    void http401VorHttp5xx_http401GewinntNicht_daKeinHttp5Enthalten() {
        // HTTP_401 enthält kein "http_5", daher gilt 401-Regel
        String result = AiFailureMessageTranslator.translate("HTTP_401");
        assertEquals("KI-Dienst: Ungültiger API-Schlüssel. Bitte in den Einstellungen prüfen.", result);
    }
}
