"""
Tests für den PDF Service.

Testet:
- Elternbrief-Generierung
- Zeugnis-Generierung
- Korrektur-Übersicht-Generierung

Note: These tests require WeasyPrint which needs system libraries (libgobject).
      Tests are skipped if WeasyPrint cannot be loaded.
"""

import pytest
import sys
import os
from datetime import datetime

# Add parent directory to path
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))

# Mark all tests in this module as requiring WeasyPrint
# These tests will be automatically skipped in CI via conftest.py
pytestmark = pytest.mark.requires_weasyprint


class TestPDFServiceImport:
    """Tests für PDF Service Import und Initialisierung."""

    def test_import_pdf_service(self):
        """Test that PDFService can be imported."""
        from services.pdf_service import PDFService
        assert PDFService is not None

    def test_import_data_classes(self):
        """Test that data classes can be imported."""
        from services.pdf_service import (
            LetterData,
            CertificateData,
            CorrectionData,
            SchoolInfo
        )
        assert LetterData is not None
        assert CertificateData is not None
        assert CorrectionData is not None
        assert SchoolInfo is not None

    def test_import_convenience_functions(self):
        """Test that convenience functions can be imported."""
        from services.pdf_service import (
            generate_letter_pdf,
            generate_certificate_pdf,
            generate_correction_pdf,
            get_pdf_service
        )
        assert callable(generate_letter_pdf)
        assert callable(generate_certificate_pdf)
        assert callable(generate_correction_pdf)
        assert callable(get_pdf_service)


class TestPDFServiceInitialization:
    """Tests für PDF Service Initialisierung."""

    def test_create_pdf_service_instance(self):
        """Test creating a PDFService instance."""
        from services.pdf_service import PDFService
        service = PDFService()
        assert service is not None
        assert service.templates_dir.exists()

    def test_get_pdf_service_singleton(self):
        """Test that get_pdf_service returns a singleton."""
        from services.pdf_service import get_pdf_service
        service1 = get_pdf_service()
        service2 = get_pdf_service()
        assert service1 is service2


class TestLetterPDFGeneration:
    """Tests für Elternbrief-PDF-Generierung."""

    def test_generate_simple_letter(self):
        """Test generating a simple letter PDF."""
        from services.pdf_service import PDFService, LetterData

        service = PDFService()
        letter_data = LetterData(
            recipient_name="Familie Müller",
            recipient_address="Musterstraße 1\n12345 Musterstadt",
            student_name="Max Müller",
            student_class="5a",
            subject="Einladung zum Elternsprechtag",
            content="Sehr geehrte Familie Müller,\n\nhiermit laden wir Sie herzlich zum Elternsprechtag ein.",
            date="15.01.2025",
            teacher_name="Frau Schmidt",
            teacher_title="Klassenlehrerin",
            letter_type="elternabend",
            tone="professional"
        )

        pdf_bytes = service.generate_letter_pdf(letter_data)

        assert pdf_bytes is not None
        assert len(pdf_bytes) > 0
        # PDF magic number check
        assert pdf_bytes[:4] == b'%PDF'

    def test_generate_letter_with_school_info(self):
        """Test generating letter with school information."""
        from services.pdf_service import PDFService, LetterData, SchoolInfo

        service = PDFService()
        school_info = SchoolInfo(
            name="Musterschule",
            address="Schulweg 10, 12345 Musterstadt",
            phone="0123-456789",
            email="info@musterschule.de",
            website="www.musterschule.de",
            principal="Dr. Hans Meier"
        )

        letter_data = LetterData(
            recipient_name="Familie Schmidt",
            recipient_address="Hauptstraße 5\n12345 Musterstadt",
            student_name="Lisa Schmidt",
            student_class="7b",
            subject="Halbjahresbericht",
            content="Sehr geehrte Eltern,\n\nanbei erhalten Sie den Halbjahresbericht.",
            date="20.01.2025",
            teacher_name="Herr Weber",
            school_info=school_info,
            letter_type="halbjahr",
            tone="formal"
        )

        pdf_bytes = service.generate_letter_pdf(letter_data)

        assert pdf_bytes is not None
        assert len(pdf_bytes) > 0
        assert pdf_bytes[:4] == b'%PDF'

    def test_generate_letter_with_legal_references(self):
        """Test generating letter with legal references."""
        from services.pdf_service import PDFService, LetterData

        service = PDFService()
        letter_data = LetterData(
            recipient_name="Familie Braun",
            recipient_address="Gartenstraße 20\n12345 Musterstadt",
            student_name="Tim Braun",
            student_class="8c",
            subject="Fehlzeiten",
            content="Sehr geehrte Eltern,\n\nwir möchten Sie über die Fehlzeiten informieren.",
            date="25.01.2025",
            teacher_name="Frau Lehmann",
            letter_type="fehlzeiten",
            tone="concerned",
            legal_references=[
                {"law": "SchulG NRW", "paragraph": "§ 42", "title": "Pflichten der Eltern"},
                {"law": "SchulG NRW", "paragraph": "§ 43", "title": "Schulpflicht"}
            ],
            gfk_principles_applied=["Beobachtung", "Bedürfnis", "Bitte"]
        )

        pdf_bytes = service.generate_letter_pdf(letter_data)

        assert pdf_bytes is not None
        assert len(pdf_bytes) > 0
        assert pdf_bytes[:4] == b'%PDF'

    def test_generate_letter_convenience_function(self):
        """Test the convenience function for letter generation."""
        from services.pdf_service import generate_letter_pdf

        letter_dict = {
            "recipient_name": "Familie Test",
            "recipient_address": "Testweg 1\n12345 Teststadt",
            "student_name": "Test Kind",
            "student_class": "3a",
            "subject": "Test-Brief",
            "content": "Dies ist ein Testbrief.",
            "date": "01.02.2025",
            "teacher_name": "Herr Test"
        }

        pdf_bytes = generate_letter_pdf(letter_dict)

        assert pdf_bytes is not None
        assert len(pdf_bytes) > 0
        assert pdf_bytes[:4] == b'%PDF'


class TestCertificatePDFGeneration:
    """Tests für Zeugnis-PDF-Generierung."""

    def test_generate_halbjahreszeugnis(self):
        """Test generating a half-year certificate."""
        from services.pdf_service import PDFService, CertificateData

        service = PDFService()
        cert_data = CertificateData(
            student_name="Anna Beispiel",
            student_birthdate="15.05.2012",
            student_class="6b",
            school_year="2024/2025",
            certificate_type="halbjahr",
            subjects=[
                {"name": "Deutsch", "grade": "2", "points": None},
                {"name": "Mathematik", "grade": "2", "points": None},
                {"name": "Englisch", "grade": "1", "points": None},
                {"name": "Geschichte", "grade": "2", "points": None},
                {"name": "Biologie", "grade": "3", "points": None},
                {"name": "Sport", "grade": "1", "points": None},
            ],
            attendance={"days_absent": 5, "days_excused": 4, "days_unexcused": 1},
            class_teacher="Frau Mustermann",
            principal="Dr. Hans Direktor",
            issue_date="31.01.2025",
            social_behavior="B",
            work_behavior="A"
        )

        pdf_bytes = service.generate_certificate_pdf(cert_data)

        assert pdf_bytes is not None
        assert len(pdf_bytes) > 0
        assert pdf_bytes[:4] == b'%PDF'

    def test_generate_jahreszeugnis(self):
        """Test generating a full-year certificate."""
        from services.pdf_service import PDFService, CertificateData

        service = PDFService()
        cert_data = CertificateData(
            student_name="Peter Schüler",
            student_birthdate="20.03.2011",
            student_class="7a",
            school_year="2024/2025",
            certificate_type="jahres",
            subjects=[
                {"name": "Deutsch", "grade": "3", "points": None},
                {"name": "Mathematik", "grade": "2", "points": None},
                {"name": "Englisch", "grade": "2", "points": None},
            ],
            attendance={"days_absent": 10, "days_excused": 10, "days_unexcused": 0},
            remarks="Versetzung in die Klasse 8a.",
            class_teacher="Herr Lehrer",
            principal="Frau Direktorin",
            issue_date="15.07.2025"
        )

        pdf_bytes = service.generate_certificate_pdf(cert_data)

        assert pdf_bytes is not None
        assert len(pdf_bytes) > 0
        assert pdf_bytes[:4] == b'%PDF'

    def test_generate_certificate_convenience_function(self):
        """Test the convenience function for certificate generation."""
        from services.pdf_service import generate_certificate_pdf

        cert_dict = {
            "student_name": "Test Schüler",
            "student_birthdate": "01.01.2012",
            "student_class": "5a",
            "school_year": "2024/2025",
            "certificate_type": "halbjahr",
            "subjects": [
                {"name": "Deutsch", "grade": "2"},
                {"name": "Mathe", "grade": "3"}
            ],
            "attendance": {"days_absent": 3, "days_excused": 3, "days_unexcused": 0},
            "class_teacher": "Herr Test",
            "principal": "Frau Test"
        }

        pdf_bytes = generate_certificate_pdf(cert_dict)

        assert pdf_bytes is not None
        assert len(pdf_bytes) > 0
        assert pdf_bytes[:4] == b'%PDF'


class TestCorrectionPDFGeneration:
    """Tests für Korrektur-PDF-Generierung."""

    def test_generate_correction_overview(self):
        """Test generating a correction overview PDF."""
        from services.pdf_service import PDFService, CorrectionData, StudentInfo

        service = PDFService()
        student = StudentInfo(
            student_id="student-001",
            name="Maria Musterschülerin",
            class_name="9a"
        )
        correction_data = CorrectionData(
            student=student,
            exam_title="Klassenarbeit Nr. 3",
            date="10.01.2025",
            subject="Mathematik",
            max_points=50,
            achieved_points=42,
            grade="2",
            percentage=84.0,
            grade_distribution={"1": 3, "2": 8, "3": 10, "4": 5, "5": 2, "6": 0},
            class_average=2.8,
            corrections=[
                {
                    "question": "Lineare Gleichungen lösen",
                    "answer": "",
                    "points": 10,
                    "feedback": "Alle Aufgaben korrekt gelöst."
                },
                {
                    "question": "Textaufgabe: Geschwindigkeit",
                    "answer": "",
                    "points": 12,
                    "feedback": "Ansatz richtig, kleiner Rechenfehler am Ende."
                },
                {
                    "question": "Geometrie: Flächenberechnung",
                    "answer": "",
                    "points": 20,
                    "feedback": "Formeln korrekt angewendet, eine Teilaufgabe fehlt."
                }
            ],
            teacher_notes="Insgesamt eine gute Leistung. Weiter so!"
        )

        pdf_bytes = service.generate_correction_pdf(correction_data)

        assert pdf_bytes is not None
        assert len(pdf_bytes) > 0
        assert pdf_bytes[:4] == b'%PDF'

    def test_generate_correction_without_feedback(self):
        """Test generating correction PDF without individual feedback."""
        from services.pdf_service import PDFService, CorrectionData, StudentInfo

        service = PDFService()
        student = StudentInfo(
            student_id="student-002",
            name="Tom Test",
            class_name="10b"
        )
        correction_data = CorrectionData(
            student=student,
            exam_title="Vokabeltest",
            date="20.01.2025",
            subject="Englisch",
            max_points=20,
            achieved_points=18,
            grade="1",
            percentage=90.0,
            grade_distribution={"1": 5, "2": 10, "3": 8, "4": 2, "5": 0, "6": 0},
            class_average=2.3,
            corrections=[
                {"question": "Teil 1: Vokabeln DE-EN", "answer": "", "points": 9},
                {"question": "Teil 2: Vokabeln EN-DE", "answer": "", "points": 9}
            ]
        )

        pdf_bytes = service.generate_correction_pdf(correction_data)

        assert pdf_bytes is not None
        assert len(pdf_bytes) > 0
        assert pdf_bytes[:4] == b'%PDF'

    def test_generate_correction_convenience_function(self):
        """Test the convenience function for correction generation."""
        from services.pdf_service import generate_correction_pdf

        correction_dict = {
            "student_id": "student-003",
            "student_name": "Test Student",
            "student_class": "8a",
            "exam_title": "Test Klausur",
            "date": "15.01.2025",
            "subject": "Physik",
            "max_points": 30,
            "achieved_points": 24,
            "grade": "2",
            "percentage": 80.0,
            "grade_distribution": {"1": 2, "2": 5, "3": 8, "4": 3, "5": 1, "6": 0},
            "class_average": 2.9,
            "corrections": [
                {"question": "Aufgabe 1", "answer": "", "points": 12, "feedback": "Gut gelöst"},
                {"question": "Aufgabe 2", "answer": "", "points": 12, "feedback": "Korrekt"}
            ],
            "teacher_notes": "Insgesamt gute Arbeit."
        }

        pdf_bytes = generate_correction_pdf(correction_dict)

        assert pdf_bytes is not None
        assert len(pdf_bytes) > 0
        assert pdf_bytes[:4] == b'%PDF'


class TestPDFServiceHelpers:
    """Tests für Hilfsfunktionen des PDF Service."""

    def test_date_format_filter(self):
        """Test the date format filter."""
        from services.pdf_service import PDFService

        service = PDFService()

        # ISO date format
        result = service._date_format("2025-01-15")
        assert result == "15.01.2025"

        # Empty value
        result = service._date_format("")
        assert result == ""

        # Already formatted
        result = service._date_format("15.01.2025")
        assert result == "15.01.2025"

    def test_grade_color_filter(self):
        """Test the grade color filter."""
        from services.pdf_service import PDFService

        service = PDFService()

        # German grades
        assert service._grade_color("1") == "#27ae60"
        assert service._grade_color("2") == "#2ecc71"
        assert service._grade_color("3") == "#f1c40f"
        assert service._grade_color("4") == "#e67e22"
        assert service._grade_color("5") == "#e74c3c"
        assert service._grade_color("6") == "#c0392b"

        # Behavior grades
        assert service._grade_color("A") == "#27ae60"
        assert service._grade_color("B") == "#2ecc71"

        # Unknown grade
        assert service._grade_color("X") == "#333333"


class TestPDFTemplates:
    """Tests für PDF Templates."""

    def test_templates_directory_created(self):
        """Test that templates directory is created."""
        from services.pdf_service import PDFService
        from pathlib import Path

        service = PDFService()
        assert service.templates_dir.exists()
        assert service.templates_dir.is_dir()

    def test_inline_templates_work(self):
        """Test that inline templates work as fallback."""
        from services.pdf_service import PDFService

        service = PDFService()

        # Test letter template
        template_html = service._get_letter_template_html()
        assert "{{ data.subject }}" in template_html
        assert "{{ data.content" in template_html

        # Test certificate template
        template_html = service._get_certificate_template_html()
        assert "{{ data.student_name }}" in template_html
        # data.subjects is used in a for loop, not direct output
        assert "data.subjects" in template_html

        # Test correction template
        template_html = service._get_correction_template_html()
        assert "{{ data.exam_title }}" in template_html
        # data.corrections is used in a for loop, not direct output
        assert "data.corrections" in template_html


# Run tests if executed directly
if __name__ == "__main__":
    pytest.main([__file__, "-v"])
