"""
PdfViewerMixin - Mixin für PDF-Viewer-Operationen.

Dieses Mixin enthält alle Methoden für die PDF-Anzeige und -Vergleich im MainWindow:
- PDF-Rendering und -Anzeige
- Alpha-Blending und Zoom
- Thumbnail-Navigation
- Drag-to-Scroll
- PDF-Dokument-Management
"""

import gc
import logging
import time
from pathlib import Path

from PySide6.QtCore import Qt, QSize, QTimer, QUrl
from PySide6.QtGui import QCursor, QPixmap, QPainter, QDesktopServices
from PySide6.QtWidgets import QLabel, QMessageBox, QSpacerItem, QSizePolicy
from PySide6.QtPdf import QPdfDocument


logger = logging.getLogger(__name__)


class PdfViewerMixin:
    """
    Mixin-Klasse für PDF-Viewer-Operationen.

    Dieses Mixin erwartet, dass die verwendende Klasse folgende Attribute hat:
    - self.ui: UI-Objekt mit Layouts, Slidern, etc.
    - self.project: Aktuelles Projekt
    - self.pdf_documents: Dict für PDF-Dokumente
    - self.current_rendered_pixmaps: Cache für gerenderte Pixmaps
    - self.fullsize_label: QLabel für Vollbild-Anzeige
    - self.thumbnail_to_page: Dict für Thumbnail-zu-Seite-Mapping
    - self.current_zoom: Aktueller Zoom-Faktor
    - self.current_page: Aktuelle Seitennummer
    - self.current_pdf: Aktueller PDF-Dateiname
    - self.is_dragging: Drag-Status
    - self.last_drag_position: Letzte Drag-Position
    - self.drag_threshold: Mindestbewegung für Drag
    - self.scroll_sensitivity: Scroll-Empfindlichkeit
    """

    def render_and_display_page(self, pdf_filename, page_num):
        """
        Rendert und zeigt eine spezifische Seite in der Vollansicht an.
        Cached die gerenderten Pixmaps für bessere Performance.

        Args:
            pdf_filename: Name der PDF-Datei
            page_num: Seitennummer (0-basiert)
        """
        logger.debug(f"Rendere Seite {page_num + 1} von {pdf_filename}")

        if pdf_filename not in self.pdf_documents:
            logger.warning(f"PDF-Dokument {pdf_filename} nicht gefunden")
            return

        start_time = time.time()

        try:
            docs = self.pdf_documents[pdf_filename]

            # Diff-Seite laden (bestimmt die Abmessungen)
            diff_doc = docs["diff"]
            page_size = diff_doc.pagePointSize(page_num)

            # Hohe Auflösung für Vollbild (entspricht ca. Matrix(2.0, 2.0) in PyMuPDF)
            scale_factor = 2.0
            render_size = QSize(int(page_size.width() * scale_factor), int(page_size.height() * scale_factor))

            # Diff-Seite rendern (immer vorhanden)
            diff_image = diff_doc.render(page_num, render_size)
            diff_pixmap = QPixmap.fromImage(diff_image)

            # Ermittle die Abmessungen für weiße Seiten
            diff_width = diff_pixmap.width()
            diff_height = diff_pixmap.height()

            # Ref-Seite prüfen und rendern oder weiße Seite erstellen
            ref_doc = docs["ref"]
            if page_num < ref_doc.pageCount():
                ref_image = ref_doc.render(page_num, render_size)
                ref_pixmap = QPixmap.fromImage(ref_image)
                logger.debug(f"Ref-Seite {page_num + 1} gerendert")
            else:
                # Erstelle weiße Seite mit gleichen Abmessungen wie Diff-Seite
                ref_pixmap = QPixmap(diff_width, diff_height)
                ref_pixmap.fill(Qt.GlobalColor.white)
                logger.debug(f"Weiße Ref-Seite {page_num + 1} erstellt")

            # New-Seite prüfen und rendern oder weiße Seite erstellen
            new_doc = docs["new"]
            if page_num < new_doc.pageCount():
                new_image = new_doc.render(page_num, render_size)
                new_pixmap = QPixmap.fromImage(new_image)
                logger.debug(f"New-Seite {page_num + 1} gerendert")
            else:
                # Erstelle weiße Seite mit gleichen Abmessungen wie Diff-Seite
                new_pixmap = QPixmap(diff_width, diff_height)
                new_pixmap.fill(Qt.GlobalColor.white)
                logger.debug(f"Weiße New-Seite {page_num + 1} erstellt")

            # Cache die gerenderten Pixmaps für schnelle Alpha/Zoom-Operationen
            self.current_rendered_pixmaps = {"ref": ref_pixmap, "diff": diff_pixmap, "new": new_pixmap}

            # Aktualisiere aktuelle Seite
            self.current_page = page_num
            self.current_pdf = pdf_filename

            # Zeige das Bild mit aktuellem Alpha- und Zoom-Wert an
            self.update_current_display()

            render_time = time.time() - start_time
            logger.debug(f"Performance: Seite {page_num + 1} gerendert in {render_time:.3f}s")

        except Exception as e:
            logger.error(f"Fehler beim Rendern der Seite {page_num + 1}: {e}", exc_info=True)

    def update_current_display(self):
        """
        Aktualisiert die Anzeige der aktuellen Seite basierend auf gecachten Pixmaps.
        Verwendet für Alpha- und Zoom-Änderungen ohne erneutes PDF-Rendering.
        """
        if not self.current_rendered_pixmaps:
            logger.warning("Keine gerenderten Pixmaps verfügbar")
            return

        if self.fullsize_label is None:
            logger.warning("Fullsize-Label ist nicht verfügbar")
            return

        try:
            # Hole die gecachten Pixmaps
            ref_pixmap = self.current_rendered_pixmaps["ref"]
            diff_pixmap = self.current_rendered_pixmaps["diff"]
            new_pixmap = self.current_rendered_pixmaps["new"]

            # Erstelle das überlagerte Bild mit aktuellem Alpha-Wert
            alpha_value = self.ui.alpha.value()
            layered_pixmap = self.create_layered_pixmap(ref_pixmap, diff_pixmap, new_pixmap, alpha_value)

            # Wende aktuellen Zoom an
            zoom_factor = self.current_zoom / 100.0
            if zoom_factor != 1.0:
                new_width = int(layered_pixmap.width() * zoom_factor)
                layered_pixmap = layered_pixmap.scaledToWidth(new_width, Qt.TransformationMode.SmoothTransformation)

            # Setze das überlagerte Bild
            self.fullsize_label.setPixmap(layered_pixmap)
            self.fullsize_label.setAlignment(Qt.AlignmentFlag.AlignHCenter)
        except RuntimeError as e:
            # C++-Objekt wurde bereits gelöscht
            logger.warning(f"Fullsize-Label wurde bereits gelöscht: {e}")
            self.fullsize_label = None

    def create_layered_pixmap(self, ref_pixmap, diff_pixmap, new_pixmap, alpha_value):
        """
        Erstellt ein übergelagertes Pixmap basierend auf dem Alpha-Wert.

        Args:
            ref_pixmap: Unterste Ebene (ref)
            diff_pixmap: Mittlere Ebene (diff)
            new_pixmap: Oberste Ebene (new)
            alpha_value: Alpha-Wert (-100 bis 100)

        Returns:
            QPixmap: Das überlagerte Bild
        """
        # Verwende die Größe des größten Bildes
        max_width = max(ref_pixmap.width(), diff_pixmap.width(), new_pixmap.width())
        max_height = max(ref_pixmap.height(), diff_pixmap.height(), new_pixmap.height())

        # Erstelle ein leeres Pixmap für das Ergebnis
        result = QPixmap(max_width, max_height)
        result.fill(Qt.GlobalColor.white)

        painter = QPainter(result)
        painter.setRenderHint(QPainter.RenderHint.Antialiasing)

        if alpha_value <= 0:
            # Alpha von -100 bis 0: Übergang von ref zu diff
            ref_opacity = abs(alpha_value) / 100
            diff_opacity = 1.0 - abs(alpha_value) / 100.0
            new_opacity = 0.0
        else:
            ref_opacity = 0.0
            diff_opacity = 1.0 - alpha_value / 100.0
            new_opacity = alpha_value / 100.0

        # Zeichne die Ebenen mit entsprechender Transparenz
        if ref_opacity > 0:
            painter.setOpacity(ref_opacity)
            painter.drawPixmap(0, 0, ref_pixmap)

        if diff_opacity > 0:
            painter.setOpacity(diff_opacity)
            painter.drawPixmap(0, 0, diff_pixmap)

        if new_opacity > 0:
            painter.setOpacity(new_opacity)
            painter.drawPixmap(0, 0, new_pixmap)

        painter.end()
        return result

    def _schedule_thumbnail_rendering(self, diff_doc, pdf_basename, thumbnail_labels, page_num):
        """Rendert Thumbnails progressiv — ein Thumbnail pro Event-Loop-Iteration."""
        if page_num >= len(thumbnail_labels):
            return

        thumbnail = thumbnail_labels[page_num]
        # Prüfe ob das Label noch existiert (Benutzer könnte inzwischen anderes PDF geöffnet haben)
        if thumbnail_labels[page_num] not in self.thumbnail_to_page:
            return

        page_size = diff_doc.pagePointSize(page_num)
        scale_factor = 200.0 / page_size.width()
        page_image = diff_doc.render(
            page_num,
            QSize(int(page_size.width() * scale_factor), int(page_size.height() * scale_factor)),
        )
        thumbnail.setPixmap(QPixmap.fromImage(page_image).scaledToWidth(200, Qt.TransformationMode.SmoothTransformation))
        thumbnail.setMinimumHeight(0)

        QTimer.singleShot(0, lambda: self._schedule_thumbnail_rendering(diff_doc, pdf_basename, thumbnail_labels, page_num + 1))

    def _clear_layout(self, layout):
        """Entfernt alle Widgets aus einem Layout."""
        if layout is not None:
            while layout.count():
                item = layout.takeAt(0)
                widget = item.widget()
                if widget is not None:
                    widget.deleteLater()

    def on_alpha_changed(self, alpha_value):
        """
        Wird ausgeführt, wenn der Alpha-Slider geändert wird.
        Optimiert: Verwendet gecachte Pixmaps statt erneutes PDF-Rendering.

        Args:
            alpha_value: Der neue Alpha-Wert (-100 bis 100)
        """
        logger.debug(f"Alpha geändert auf {alpha_value}")

        start_time = time.time()
        # Verwende gecachte Pixmaps für schnelle Alpha-Änderungen
        self.update_current_display()
        alpha_time = time.time() - start_time
        logger.debug(f"Alpha-Update in {alpha_time:.6f}s")

    def on_thumbnail_clicked(self, event, thumbnail):
        """
        Wird ausgeführt, wenn ein Thumbnail angeklickt wird.

        Args:
            event: Das Maus-Event
            thumbnail: Das geklickte Thumbnail-Label
        """
        page_info = self.thumbnail_to_page.get(thumbnail)
        if page_info:
            pdf_filename = page_info["pdf_filename"]
            page_num = page_info["page_num"]

            logger.debug(f"Thumbnail für Seite {page_num + 1} von {pdf_filename} wurde angeklickt")

            # Rendere und zeige die gewählte Seite an
            self.render_and_display_page(pdf_filename, page_num)

    def apply_zoom(self, zoom_value):
        """
        Wendet den Zoom-Faktor auf das aktuelle Bild an.
        Optimiert: Verwendet gecachte Pixmaps statt erneutes PDF-Rendering.

        Args:
            zoom_value: Der neue Zoom-Wert (in Prozent)
        """
        self.current_zoom = zoom_value
        logger.debug(f"Zoom geändert auf {zoom_value}%")

        # Verwende gecachte Pixmaps für schnelle Zoom-Änderungen
        self.update_current_display()

    def on_fullsize_mouse_press(self, event, fullsize_label):
        """Wird ausgeführt, wenn die Maustaste auf einem großen Bild gedrückt wird."""
        if event.button() == Qt.MouseButton.LeftButton:
            self.is_dragging = True
            self.last_drag_position = event.globalPosition().toPoint()
            fullsize_label.setCursor(QCursor(Qt.CursorShape.ClosedHandCursor))

    def on_fullsize_mouse_move(self, event, fullsize_label):
        """Wird ausgeführt, wenn die Maus über einem großen Bild bewegt wird."""
        if self.is_dragging and self.last_drag_position is not None:
            current_pos = event.globalPosition().toPoint()
            delta = current_pos - self.last_drag_position

            if abs(delta.x()) >= self.drag_threshold or abs(delta.y()) >= self.drag_threshold:
                v_scrollbar = self.ui.scrollArea_2.verticalScrollBar()
                h_scrollbar = self.ui.scrollArea_2.horizontalScrollBar()

                scroll_delta_y = int(-delta.y() * self.scroll_sensitivity)
                scroll_delta_x = int(-delta.x() * self.scroll_sensitivity)

                new_v_value = v_scrollbar.value() + scroll_delta_y
                new_h_value = h_scrollbar.value() + scroll_delta_x

                v_scrollbar.setValue(new_v_value)
                h_scrollbar.setValue(new_h_value)

                self.last_drag_position = current_pos

    def on_fullsize_mouse_release(self, event, fullsize_label):
        """Wird ausgeführt, wenn die Maustaste auf einem großen Bild losgelassen wird."""
        if event.button() == Qt.MouseButton.LeftButton:
            self.is_dragging = False
            self.last_drag_position = None
            fullsize_label.setCursor(QCursor(Qt.CursorShape.OpenHandCursor))

    def _load_pdf_for_comparison(self, xml_file_path: Path, xsl_id_str: str):
        """
        Lädt die PDFs (diff, ref, new) einer Transformation in den Vergleichs-Viewer.

        Args:
            xml_file_path: Pfad zur XML-Datei (relativ)
            xsl_id_str: XSL-ID als String (z.B. "2002_1_128")
        """
        try:
            if not self.project:
                QMessageBox.warning(self, "Fehler", "Kein Projekt geöffnet")
                return

            # Ermittle PDF-Dateinamen basierend auf XML und XSL-ID
            xml_stem = xml_file_path.stem
            pdf_basename = f"{xml_stem}_xsl_{xsl_id_str}.pdf"

            # Pfade zu den drei PDFs
            diff_dir = self.project.project_dir / "diff"
            ref_dir = self.project.project_dir / "ref"
            new_dir = self.project.project_dir / "new"

            diff_pdf_path = diff_dir / pdf_basename
            ref_pdf_path = ref_dir / pdf_basename
            new_pdf_path = new_dir / pdf_basename

            # Prüfe ob PDFs existieren
            if not diff_pdf_path.exists():
                QMessageBox.information(self, "Keine Diff-PDF", f"Diff-PDF nicht gefunden:\n{pdf_basename}")
                return

            if not ref_pdf_path.exists() or not new_pdf_path.exists():
                QMessageBox.warning(
                    self,
                    "Fehlende PDFs",
                    f"Ref-PDF oder New-PDF nicht gefunden:\n{pdf_basename}\n\nNur Diff-PDF vorhanden.",
                )
                return

            logger.info(f"Lade PDFs für Vergleich: {pdf_basename}")

            # Entferne bestehende Widgets aus den Layouts
            self._clear_layout(self.ui.verticalLayout_2)
            self._clear_layout(self.ui.verticalLayout_3)

            # Setze kompaktes Spacing für Thumbnail-Layout
            self.ui.verticalLayout_2.setSpacing(5)  # Minimaler Abstand zwischen Widgets
            self.ui.verticalLayout_2.setContentsMargins(0, 0, 0, 0)  # Keine Ränder

            # Dicts zurücksetzen
            self.thumbnail_to_page = {}
            self.pdf_documents = {}
            self.current_rendered_pixmaps = None
            self.fullsize_label = None  # Label wurde durch _clear_layout gelöscht

            # Alle drei PDF-Dateien öffnen mit QtPdf
            diff_doc = QPdfDocument()
            ref_doc = QPdfDocument()
            new_doc = QPdfDocument()

            # PDF-Dateien laden
            diff_doc.load(str(diff_pdf_path))
            ref_doc.load(str(ref_pdf_path))
            new_doc.load(str(new_pdf_path))

            # Warten bis PDFs geladen sind
            if (
                diff_doc.status() != QPdfDocument.Status.Ready
                or ref_doc.status() != QPdfDocument.Status.Ready
                or new_doc.status() != QPdfDocument.Status.Ready
            ):
                QMessageBox.critical(self, "Fehler", f"Fehler beim Laden der PDFs:\n{pdf_basename}")
                return

            # PDF-Dokumente speichern
            self.pdf_documents[pdf_basename] = {"diff": diff_doc, "ref": ref_doc, "new": new_doc}

            # PDF-Pfade für System-Viewer speichern
            self.current_ref_pdf_path = ref_pdf_path
            self.current_new_pdf_path = new_pdf_path

            # Buttons zum Öffnen der PDFs im System-Viewer aktivieren
            self.ui.view_ref_pdf.setEnabled(True)
            self.ui.view_new_pdf.setEnabled(True)

            # Slider aktivieren
            self.ui.alpha.setEnabled(True)
            self.ui.zoom.setEnabled(True)

            logger.info(f"PDFs geladen: {pdf_basename}")
            logger.info(f"  diff: {diff_doc.pageCount()} Seiten")
            logger.info(f"  ref: {ref_doc.pageCount()} Seiten")
            logger.info(f"  new: {new_doc.pageCount()} Seiten")

            # Nehme die Seitenzahl der diff-PDF als Basis
            max_pages = diff_doc.pageCount()

            # Erstelle Placeholder-Labels für alle Seiten (sofort, ohne Rendern)
            thumbnail_labels = []
            for page_num in range(max_pages):
                thumbnail = QLabel()
                thumbnail.setObjectName(f"thumbnail_{pdf_basename}_page_{page_num + 1}")
                thumbnail.setText(f"Seite {page_num + 1}\n…")
                thumbnail.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
                thumbnail.setMouseTracking(True)
                thumbnail.setAlignment(Qt.AlignmentFlag.AlignCenter)
                thumbnail.setMinimumHeight(150)
                self.ui.verticalLayout_2.addWidget(thumbnail)

                thumbnail_info = QLabel(f"Seite {page_num + 1}")
                thumbnail_info.setAlignment(Qt.AlignmentFlag.AlignCenter)
                thumbnail_info.setMaximumHeight(18)
                thumbnail_info.setContentsMargins(0, 0, 0, 0)
                self.ui.verticalLayout_2.addWidget(thumbnail_info)

                self.thumbnail_to_page[thumbnail] = {"pdf_filename": pdf_basename, "page_num": page_num}
                thumbnail.mousePressEvent = lambda event, t=thumbnail: self.on_thumbnail_clicked(event, t)
                thumbnail_labels.append(thumbnail)

            # Thumbnails progressiv rendern (nicht blockierend)
            self._schedule_thumbnail_rendering(diff_doc, pdf_basename, thumbnail_labels, 0)

            # Füge expandierenden Spacer am Ende hinzu, damit Thumbnails oben bleiben
            spacer = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding)
            self.ui.verticalLayout_2.addItem(spacer)

            # Erstelle das Vollbild-Label für die rechte Spalte (falls noch nicht vorhanden)
            if self.fullsize_label is None:
                self.fullsize_label = QLabel()
                self.fullsize_label.setObjectName("fullsize_current_page")
                self.fullsize_label.setAlignment(Qt.AlignmentFlag.AlignHCenter)
                self.fullsize_label.setCursor(QCursor(Qt.CursorShape.OpenHandCursor))
                self.ui.verticalLayout_3.addWidget(self.fullsize_label)

                # Drag-to-Scroll Events für das große Bild einrichten
                self.fullsize_label.mousePressEvent = lambda event: self.on_fullsize_mouse_press(
                    event, self.fullsize_label
                )
                self.fullsize_label.mouseMoveEvent = lambda event: self.on_fullsize_mouse_move(
                    event, self.fullsize_label
                )
                self.fullsize_label.mouseReleaseEvent = lambda event: self.on_fullsize_mouse_release(
                    event, self.fullsize_label
                )

            # Setze die aktuelle PDF
            self.current_pdf = pdf_basename

            # Speichere Diff-PDF-Informationen für Accept Changes
            self.current_diff_xml_path = xml_file_path
            self.current_diff_xsl_id = xsl_id_str

            # Aktiviere Accept-Changes-Button
            self.ui.accept_changes.setEnabled(True)

            # Zeige die erste Seite initial an
            self.render_and_display_page(pdf_basename, 0)

            logger.info(f"PDF-Vergleich geladen: {pdf_basename}")

        except Exception as e:
            logger.error(f"Fehler beim Laden der PDFs für Vergleich: {e}")
            QMessageBox.critical(self, "Fehler", f"Konnte PDFs nicht laden:\n{str(e)}")

    def _close_all_pdf_documents(self):
        """Schließt alle geöffneten PDF-Dokumente explizit (wichtig für Windows)."""
        if self.pdf_documents:
            for pdf_basename, docs in self.pdf_documents.items():
                for doc_type, doc in docs.items():
                    if doc:
                        doc.close()
                        logger.debug(f"PDF-Dokument geschlossen: {pdf_basename} ({doc_type})")

            # Lösche alle Referenzen
            self.pdf_documents.clear()

            # Lösche gerenderte Pixmaps
            self.current_rendered_pixmaps = None

            # Erzwinge Garbage Collection um Dateihandles freizugeben (wichtig für Windows)
            gc.collect()

            logger.info("Alle PDF-Dokumente geschlossen und Referenzen freigegeben")

    def _clear_pdf_viewer(self):
        """Leert den PDF-Viewer und alle Thumbnails."""
        # Schließe alle PDF-Dokumente explizit (wichtig für Windows)
        self._close_all_pdf_documents()

        # Entferne Widgets aus Layouts
        self._clear_layout(self.ui.verticalLayout_2)
        self._clear_layout(self.ui.verticalLayout_3)

        # Zurücksetzen der Datenstrukturen
        self.thumbnail_to_page = {}
        self.pdf_documents = {}
        self.current_rendered_pixmaps = None
        self.fullsize_label = None
        self.current_pdf = None
        self.current_diff_xml_path = None
        self.current_diff_xsl_id = None

        # PDF-Pfade zurücksetzen und Buttons deaktivieren
        self.current_ref_pdf_path = None
        self.current_new_pdf_path = None
        self.ui.view_ref_pdf.setEnabled(False)
        self.ui.view_new_pdf.setEnabled(False)
        self.ui.accept_changes.setEnabled(False)

        # Slider deaktivieren
        self.ui.alpha.setEnabled(False)
        self.ui.zoom.setEnabled(False)

        logger.info("PDF-Viewer geleert")

    def _on_view_ref_pdf_clicked(self):
        """
        Handler für view_ref_pdf Button.
        Öffnet die Referenz-PDF im systemseitig installierten PDF-Viewer.
        """
        if not self.current_ref_pdf_path or not self.current_ref_pdf_path.exists():
            QMessageBox.warning(self, "Fehler", "Referenz-PDF nicht gefunden")
            logger.warning("Referenz-PDF nicht verfügbar")
            return

        logger.info(f"Öffne Referenz-PDF im System-Viewer: {self.current_ref_pdf_path}")
        url = QUrl.fromLocalFile(str(self.current_ref_pdf_path))
        if not QDesktopServices.openUrl(url):
            QMessageBox.critical(self, "Fehler", f"Konnte Referenz-PDF nicht öffnen:\n{self.current_ref_pdf_path}")
            logger.error(f"Fehler beim Öffnen der Referenz-PDF: {self.current_ref_pdf_path}")

    def _load_ref_pdf_for_display(self, xml_file_path: Path, xsl_id_str: str):
        """
        Lädt nur die Ref-PDF in den Viewer (wenn keine Diff-PDF vorhanden ist).

        Args:
            xml_file_path: Pfad zur XML-Datei (relativ)
            xsl_id_str: XSL-ID als String
        """
        try:
            if not self.project:
                return

            xml_stem = xml_file_path.stem
            pdf_basename = f"{xml_stem}_xsl_{xsl_id_str}.pdf"
            ref_pdf_path = self.project.project_dir / "ref" / pdf_basename

            if not ref_pdf_path.exists():
                if self.pdf_documents:
                    self._clear_pdf_viewer()
                return

            logger.info(f"Lade Ref-PDF für Anzeige: {pdf_basename}")

            self._clear_layout(self.ui.verticalLayout_2)
            self._clear_layout(self.ui.verticalLayout_3)
            self.ui.verticalLayout_2.setSpacing(5)
            self.ui.verticalLayout_2.setContentsMargins(0, 0, 0, 0)

            self.thumbnail_to_page = {}
            self.pdf_documents = {}
            self.current_rendered_pixmaps = None
            self.fullsize_label = None

            ref_doc = QPdfDocument()
            ref_doc.load(str(ref_pdf_path))

            if ref_doc.status() != QPdfDocument.Status.Ready:
                QMessageBox.critical(self, "Fehler", f"Fehler beim Laden der Ref-PDF:\n{pdf_basename}")
                return

            # Ref-Doc in allen drei Slots speichern, damit render_and_display_page funktioniert
            self.pdf_documents[pdf_basename] = {"diff": ref_doc, "ref": ref_doc, "new": ref_doc}

            self.current_ref_pdf_path = ref_pdf_path
            self.current_new_pdf_path = None
            self.ui.view_ref_pdf.setEnabled(True)
            self.ui.view_new_pdf.setEnabled(False)

            # Alpha deaktivieren (Blending nicht sinnvoll ohne Diff), Zoom aktivieren
            self.ui.alpha.setValue(0)
            self.ui.alpha.setEnabled(False)
            self.ui.zoom.setEnabled(True)

            self.ui.accept_changes.setEnabled(False)

            max_pages = ref_doc.pageCount()
            logger.info(f"Ref-PDF geladen: {pdf_basename}, {max_pages} Seiten")

            thumbnail_labels = []
            for page_num in range(max_pages):
                thumbnail = QLabel()
                thumbnail.setObjectName(f"thumbnail_{pdf_basename}_page_{page_num + 1}")
                thumbnail.setText(f"Seite {page_num + 1}\n…")
                thumbnail.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
                thumbnail.setMouseTracking(True)
                thumbnail.setAlignment(Qt.AlignmentFlag.AlignCenter)
                thumbnail.setMinimumHeight(150)
                self.ui.verticalLayout_2.addWidget(thumbnail)

                thumbnail_info = QLabel(f"Seite {page_num + 1}")
                thumbnail_info.setAlignment(Qt.AlignmentFlag.AlignCenter)
                thumbnail_info.setMaximumHeight(18)
                thumbnail_info.setContentsMargins(0, 0, 0, 0)
                self.ui.verticalLayout_2.addWidget(thumbnail_info)

                self.thumbnail_to_page[thumbnail] = {"pdf_filename": pdf_basename, "page_num": page_num}
                thumbnail.mousePressEvent = lambda event, t=thumbnail: self.on_thumbnail_clicked(event, t)
                thumbnail_labels.append(thumbnail)

            self._schedule_thumbnail_rendering(ref_doc, pdf_basename, thumbnail_labels, 0)

            spacer = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding)
            self.ui.verticalLayout_2.addItem(spacer)

            if self.fullsize_label is None:
                self.fullsize_label = QLabel()
                self.fullsize_label.setObjectName("fullsize_current_page")
                self.fullsize_label.setAlignment(Qt.AlignmentFlag.AlignHCenter)
                self.fullsize_label.setCursor(QCursor(Qt.CursorShape.OpenHandCursor))
                self.ui.verticalLayout_3.addWidget(self.fullsize_label)

                self.fullsize_label.mousePressEvent = lambda event: self.on_fullsize_mouse_press(
                    event, self.fullsize_label
                )
                self.fullsize_label.mouseMoveEvent = lambda event: self.on_fullsize_mouse_move(
                    event, self.fullsize_label
                )
                self.fullsize_label.mouseReleaseEvent = lambda event: self.on_fullsize_mouse_release(
                    event, self.fullsize_label
                )

            self.current_pdf = pdf_basename
            self.current_diff_xml_path = None
            self.current_diff_xsl_id = None

            self.render_and_display_page(pdf_basename, 0)
            logger.info(f"Ref-PDF-Anzeige geladen: {pdf_basename}")

        except Exception as e:
            logger.error(f"Fehler beim Laden der Ref-PDF: {e}")
            QMessageBox.critical(self, "Fehler", f"Konnte Ref-PDF nicht laden:\n{str(e)}")

    def _on_view_new_pdf_clicked(self):
        """
        Handler für view_new_pdf Button.
        Öffnet die neue PDF im systemseitig installierten PDF-Viewer.
        """
        if not self.current_new_pdf_path or not self.current_new_pdf_path.exists():
            QMessageBox.warning(self, "Fehler", "Neue PDF nicht gefunden")
            logger.warning("Neue PDF nicht verfügbar")
            return

        logger.info(f"Öffne neue PDF im System-Viewer: {self.current_new_pdf_path}")
        url = QUrl.fromLocalFile(str(self.current_new_pdf_path))
        if not QDesktopServices.openUrl(url):
            QMessageBox.critical(self, "Fehler", f"Konnte neue PDF nicht öffnen:\n{self.current_new_pdf_path}")
            logger.error(f"Fehler beim Öffnen der neuen PDF: {self.current_new_pdf_path}")
