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

import java.util.Objects;

import de.gecheckt.pdf.umbenenner.application.port.in.DocumentCompletionStatus;
import de.gecheckt.pdf.umbenenner.domain.model.ProcessingStatus;

/**
 * Zentrale Mapping-Klasse für die visuelle Darstellung von Verarbeitungsstatus in der GUI.
 * <p>
 * Diese Klasse ist die einzige autoritative Quelle für Status-Icons, CSS-Farben,
 * Tooltip-Texte und Summary-Kategorielabels aller {@link DocumentCompletionStatus}-Werte.
 * Alle Anzeigeorte im GUI-Adapter (Ergebnistabelle, Detailbereich, Summary-Banner)
 * beziehen ihre Darstellungsinformationen ausschließlich über diese Klasse.
 * <p>
 * Farbe ist niemals das einzige Unterscheidungsmerkmal: Icon und Tooltip-Text beschreiben
 * den Status vollständig auch ohne Farb­wahrnehmung.
 * <p>
 * Diese Klasse enthält keine JavaFX-Typen; sie ist rein datenhaltend und zustandslos.
 * Alle Methoden sind statisch.
 */
public final class ProcessingStatusPresentation {
    private static final String STATUS_NOT_NULL = "status darf nicht null sein";



    // -------------------------------------------------------------------------
    // Icons (Unicode-Zeichen, zuverlässig darstellbar unter Windows 10+)
    // -------------------------------------------------------------------------

    /** Icon für {@link DocumentCompletionStatus#SUCCESS}. */
    public static final String ICON_SUCCESS = "✓";           // CHECK MARK

    /** Icon für {@link DocumentCompletionStatus#FAILED_RETRYABLE}. */
    public static final String ICON_FAILED_RETRYABLE = "↻";  // CLOCKWISE OPEN CIRCLE ARROW

    /** Icon für {@link DocumentCompletionStatus#FAILED_PERMANENT}. */
    public static final String ICON_FAILED_PERMANENT = "×";  // MULTIPLICATION SIGN

    /** Icon für {@link DocumentCompletionStatus#SKIPPED_ALREADY_PROCESSED}. */
    public static final String ICON_SKIPPED_ALREADY_PROCESSED = "≡"; // IDENTICAL TO

    /** Icon für {@link DocumentCompletionStatus#SKIPPED_FINAL_FAILURE}. */
    public static final String ICON_SKIPPED_FINAL_FAILURE = "⊘"; // CIRCLED DIVISION SLASH

    // -------------------------------------------------------------------------
    // CSS-Farben (Hex-Strings für JavaFX setStyle)
    // -------------------------------------------------------------------------

    /** CSS-Farbe für {@link DocumentCompletionStatus#SUCCESS}. */
    public static final String COLOR_SUCCESS = "#2e7d32";             // Grün

    /** CSS-Farbe für {@link DocumentCompletionStatus#FAILED_RETRYABLE}. */
    public static final String COLOR_FAILED_RETRYABLE = "#d98200";    // Orange

    /** CSS-Farbe für {@link DocumentCompletionStatus#FAILED_PERMANENT}. */
    public static final String COLOR_FAILED_PERMANENT = "#c62828";    // Rot

    /** CSS-Farbe für {@link DocumentCompletionStatus#SKIPPED_ALREADY_PROCESSED}. */
    public static final String COLOR_SKIPPED_ALREADY_PROCESSED = "#757575"; // Grau

    /** CSS-Farbe für {@link DocumentCompletionStatus#SKIPPED_FINAL_FAILURE}. */
    public static final String COLOR_SKIPPED_FINAL_FAILURE = "#424242";     // Dunkelgrau

    // -------------------------------------------------------------------------
    // Tooltip-Texte (deutsche Benutzertexte, gemäß Spezifikation)
    // -------------------------------------------------------------------------

    /** Tooltip für {@link DocumentCompletionStatus#SUCCESS}. */
    public static final String TOOLTIP_SUCCESS =
            "Erfolgreich verarbeitet und umbenannt.";

    /** Tooltip für {@link DocumentCompletionStatus#FAILED_RETRYABLE}. */
    public static final String TOOLTIP_FAILED_RETRYABLE =
            "Temporärer Fehler – wird beim nächsten Lauf automatisch erneut versucht.";

    /** Tooltip für {@link DocumentCompletionStatus#FAILED_PERMANENT}. */
    public static final String TOOLTIP_FAILED_PERMANENT =
            "Dauerhaft nicht verarbeitbar – z. B. kein Textinhalt (Foto-PDF), Passwortschutz "
                    + "oder beschädigte Datei. Kein weiterer automatischer Versuch.";

    /** Tooltip für {@link DocumentCompletionStatus#SKIPPED_ALREADY_PROCESSED}. */
    public static final String TOOLTIP_SKIPPED_ALREADY_PROCESSED =
            "Übersprungen – wurde bereits in einem früheren Lauf erfolgreich verarbeitet.";

    /** Tooltip für {@link DocumentCompletionStatus#SKIPPED_FINAL_FAILURE}. */
    public static final String TOOLTIP_SKIPPED_FINAL_FAILURE =
            "Endgültig übersprungen nach wiederholten Fehlern.";

    // -------------------------------------------------------------------------
    // Detailtext für FAILED_PERMANENT (Erklärung im Detailbereich)
    // -------------------------------------------------------------------------

    /**
     * Erweiterter Erklärungstext, der im Detailbereich bei dauerhaft fehlgeschlagenen
     * Dokumenten angezeigt wird.
     */
    public static final String DETAIL_TEXT_FAILED_PERMANENT =
            "Diese Datei kann nicht verarbeitet werden. Mögliche Ursachen: "
                    + "kein lesbarer Text (z. B. gescanntes Foto ohne OCR), Passwortschutz "
                    + "oder beschädigte Datei. "
                    + "Sie können den Status manuell zurücksetzen, wenn Sie die Ursache behoben haben.";

    // -------------------------------------------------------------------------
    // Summary-Kategorielabels
    // -------------------------------------------------------------------------

    /** Summary-Kategorie für {@link DocumentCompletionStatus#SUCCESS}. */
    public static final String SUMMARY_CATEGORY_SUCCESS = "erfolgreich";

    /** Summary-Kategorie für {@link DocumentCompletionStatus#FAILED_RETRYABLE}. */
    public static final String SUMMARY_CATEGORY_FAILED_RETRYABLE = "wird wiederholt";

    /** Summary-Kategorie für {@link DocumentCompletionStatus#FAILED_PERMANENT}. */
    public static final String SUMMARY_CATEGORY_FAILED_PERMANENT = "fehlgeschlagen";

    /** Summary-Kategorie für {@link DocumentCompletionStatus#SKIPPED_ALREADY_PROCESSED}. */
    public static final String SUMMARY_CATEGORY_SKIPPED_ALREADY_PROCESSED = "übersprungen";

    /** Summary-Kategorie für {@link DocumentCompletionStatus#SKIPPED_FINAL_FAILURE}. */
    public static final String SUMMARY_CATEGORY_SKIPPED_FINAL_FAILURE = "endgültig übersprungen";

    // -------------------------------------------------------------------------
    // Record-Typ für gebündelte Darstellungsinformationen
    // -------------------------------------------------------------------------

    /**
     * Gebündelte visuelle Darstellungsinformationen für einen Verarbeitungsstatus.
     *
     * @param icon              Unicode-Zeichen als Status-Icon; nie leer
     * @param cssColor          CSS-Hex-Farbe für das Icon, z. B. {@code "#2e7d32"}; nie leer
     * @param tooltipText       Deutschsprachiger Tooltip-Text; nie leer
     * @param summaryCategoryLabel  Kategorie-Bezeichnung für das Summary-Banner; nie leer
     */
    public record StatusVisuals(
            String icon,
            String cssColor,
            String tooltipText,
            String summaryCategoryLabel) {

        /**
         * Kompakter Konstruktor zur Pflichtfeld-Validierung.
         *
         * @throws NullPointerException     wenn ein Feld {@code null} ist
         * @throws IllegalArgumentException wenn ein String-Feld leer ist
         */
        public StatusVisuals {
            Objects.requireNonNull(icon, "icon muss gesetzt sein");
            Objects.requireNonNull(cssColor, "cssColor muss gesetzt sein");
            Objects.requireNonNull(tooltipText, "tooltipText muss gesetzt sein");
            Objects.requireNonNull(summaryCategoryLabel, "summaryCategoryLabel muss gesetzt sein");
            if (icon.isBlank()) throw new IllegalArgumentException("icon darf nicht leer sein");
            if (cssColor.isBlank()) throw new IllegalArgumentException("cssColor darf nicht leer sein");
            if (tooltipText.isBlank()) throw new IllegalArgumentException("tooltipText darf nicht leer sein");
            if (summaryCategoryLabel.isBlank())
                throw new IllegalArgumentException("summaryCategoryLabel darf nicht leer sein");
        }
    }

    // -------------------------------------------------------------------------
    // Zentrale Mapping-Methoden
    // -------------------------------------------------------------------------

    /**
     * Liefert das Status-Icon für den angegebenen Verarbeitungsstatus.
     *
     * @param status der Verarbeitungsstatus; darf nicht {@code null} sein
     * @return das zugehörige Unicode-Zeichen; nie leer
     * @throws NullPointerException wenn {@code status} {@code null} ist
     */
    public static String iconFor(DocumentCompletionStatus status) {
        Objects.requireNonNull(status, STATUS_NOT_NULL);
        return switch (status) {
            case SUCCESS -> ICON_SUCCESS;
            case FAILED_RETRYABLE -> ICON_FAILED_RETRYABLE;
            case FAILED_PERMANENT -> ICON_FAILED_PERMANENT;
            case SKIPPED_ALREADY_PROCESSED -> ICON_SKIPPED_ALREADY_PROCESSED;
            case SKIPPED_FINAL_FAILURE -> ICON_SKIPPED_FINAL_FAILURE;
        };
    }

    /**
     * Liefert die CSS-Hex-Farbe für das Status-Icon des angegebenen Verarbeitungsstatus.
     * <p>
     * Die Farbe ist nie das einzige Unterscheidungsmerkmal – Icon und Tooltip-Text
     * beschreiben den Status unabhängig von der Farbe eindeutig.
     *
     * @param status der Verarbeitungsstatus; darf nicht {@code null} sein
     * @return die CSS-Hex-Farbe (z. B. {@code "#2e7d32"}); nie leer
     * @throws NullPointerException wenn {@code status} {@code null} ist
     */
    public static String cssColorFor(DocumentCompletionStatus status) {
        Objects.requireNonNull(status, STATUS_NOT_NULL);
        return switch (status) {
            case SUCCESS -> COLOR_SUCCESS;
            case FAILED_RETRYABLE -> COLOR_FAILED_RETRYABLE;
            case FAILED_PERMANENT -> COLOR_FAILED_PERMANENT;
            case SKIPPED_ALREADY_PROCESSED -> COLOR_SKIPPED_ALREADY_PROCESSED;
            case SKIPPED_FINAL_FAILURE -> COLOR_SKIPPED_FINAL_FAILURE;
        };
    }

    /**
     * Liefert den deutschsprachigen Tooltip-Text für den angegebenen Verarbeitungsstatus.
     *
     * @param status der Verarbeitungsstatus; darf nicht {@code null} sein
     * @return der Tooltip-Text; nie leer
     * @throws NullPointerException wenn {@code status} {@code null} ist
     */
    public static String tooltipFor(DocumentCompletionStatus status) {
        Objects.requireNonNull(status, STATUS_NOT_NULL);
        return switch (status) {
            case SUCCESS -> TOOLTIP_SUCCESS;
            case FAILED_RETRYABLE -> TOOLTIP_FAILED_RETRYABLE;
            case FAILED_PERMANENT -> TOOLTIP_FAILED_PERMANENT;
            case SKIPPED_ALREADY_PROCESSED -> TOOLTIP_SKIPPED_ALREADY_PROCESSED;
            case SKIPPED_FINAL_FAILURE -> TOOLTIP_SKIPPED_FINAL_FAILURE;
        };
    }

    /**
     * Liefert die Summary-Kategorie-Bezeichnung für den angegebenen Verarbeitungsstatus.
     * Diese Kategorie wird im Summary-Banner nach einem Lauf angezeigt.
     *
     * @param status der Verarbeitungsstatus; darf nicht {@code null} sein
     * @return die Kategorienbezeichnung; nie leer
     * @throws NullPointerException wenn {@code status} {@code null} ist
     */
    public static String summaryCategoryFor(DocumentCompletionStatus status) {
        Objects.requireNonNull(status, STATUS_NOT_NULL);
        return switch (status) {
            case SUCCESS -> SUMMARY_CATEGORY_SUCCESS;
            case FAILED_RETRYABLE -> SUMMARY_CATEGORY_FAILED_RETRYABLE;
            case FAILED_PERMANENT -> SUMMARY_CATEGORY_FAILED_PERMANENT;
            case SKIPPED_ALREADY_PROCESSED -> SUMMARY_CATEGORY_SKIPPED_ALREADY_PROCESSED;
            case SKIPPED_FINAL_FAILURE -> SUMMARY_CATEGORY_SKIPPED_FINAL_FAILURE;
        };
    }

    /**
     * Liefert alle gebündelten visuellen Darstellungsinformationen für den angegebenen
     * Verarbeitungsstatus in einem einzigen Objekt.
     *
     * @param status der Verarbeitungsstatus; darf nicht {@code null} sein
     * @return ein befülltes {@link StatusVisuals}-Record; nie {@code null}
     * @throws NullPointerException wenn {@code status} {@code null} ist
     */
    public static StatusVisuals visualsFor(DocumentCompletionStatus status) {
        Objects.requireNonNull(status, STATUS_NOT_NULL);
        return new StatusVisuals(
                iconFor(status),
                cssColorFor(status),
                tooltipFor(status),
                summaryCategoryFor(status));
    }

    // -------------------------------------------------------------------------
    // Mapping für ProcessingStatus (alle acht Domain-Statuswerte)
    // -------------------------------------------------------------------------

    /**
     * Liefert den deutschsprachigen Anzeigetext mit Icon für den angegebenen
     * Domain-Verarbeitungsstatus. Kein Enum-Rohname darf für Endnutzer sichtbar sein.
     *
     * @param status der Domain-Verarbeitungsstatus; darf nicht {@code null} sein
     * @return der Anzeigetext mit vorangestelltem Icon; nie leer
     * @throws NullPointerException wenn {@code status} {@code null} ist
     */
    public static String displayTextFor(ProcessingStatus status) {
        Objects.requireNonNull(status, STATUS_NOT_NULL);
        return switch (status) {
            case SUCCESS -> "✓ Erfolgreich";
            case FAILED_RETRYABLE -> "↻ Temporärer Fehler";
            case FAILED_FINAL -> "× Dauerhaft fehlgeschlagen";
            case SKIPPED_ALREADY_PROCESSED -> "≡ Bereits verarbeitet";
            case SKIPPED_FINAL_FAILURE -> "⊘ Endgültig übersprungen";
            case READY_FOR_AI -> "⟳ Wartet auf Verarbeitung";
            case PROPOSAL_READY -> "◇ Vorschlag vorhanden";
            case PROCESSING -> "▶ In Bearbeitung";
        };
    }

    /** Nicht instanziierbar – reine Utility-Klasse. */
    private ProcessingStatusPresentation() {
        throw new UnsupportedOperationException("Nicht instanziierbar");
    }
}
