"""
Tests für die Letters API.

Testet:
- CRUD-Operationen für Elternbriefe
- PDF-Export
- GFK-Verbesserungsvorschläge

Note: Some tests require WeasyPrint which needs system libraries.
"""

import pytest
from fastapi.testclient import TestClient
from unittest.mock import patch, AsyncMock, MagicMock
import sys
import os

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

# Check if WeasyPrint is available (required for PDF endpoints)
try:
    import weasyprint
    WEASYPRINT_AVAILABLE = True
except (ImportError, OSError):
    WEASYPRINT_AVAILABLE = False


class TestLettersAPIImport:
    """Tests für Letters API Import."""

    def test_import_letters_api(self):
        """Test that letters_api can be imported."""
        from letters_api import router
        assert router is not None

    def test_import_enums(self):
        """Test that enums can be imported."""
        from letters_api import LetterType, LetterTone, LetterStatus
        assert LetterType is not None
        assert LetterTone is not None
        assert LetterStatus is not None

    def test_import_models(self):
        """Test that Pydantic models can be imported."""
        from letters_api import (
            LetterCreateRequest,
            LetterUpdateRequest,
            LetterResponse,
            LetterListResponse,
            ExportPDFRequest,
            ImproveRequest,
            ImproveResponse
        )
        assert LetterCreateRequest is not None
        assert LetterResponse is not None


class TestLetterTypes:
    """Tests für Brieftypen."""

    def test_letter_types_values(self):
        """Test that all letter types have correct values."""
        from letters_api import LetterType

        expected_types = ["general", "halbjahr", "fehlzeiten", "elternabend", "lob", "custom"]
        actual_types = [t.value for t in LetterType]

        for expected in expected_types:
            assert expected in actual_types

    def test_letter_tones_values(self):
        """Test that all tones have correct values."""
        from letters_api import LetterTone

        expected_tones = ["formal", "professional", "warm", "concerned", "appreciative"]
        actual_tones = [t.value for t in LetterTone]

        for expected in expected_tones:
            assert expected in actual_tones


class TestLetterCreateRequest:
    """Tests für LetterCreateRequest Model."""

    def test_create_minimal_request(self):
        """Test creating a request with minimal required fields."""
        from letters_api import LetterCreateRequest

        request = LetterCreateRequest(
            recipient_name="Familie Müller",
            recipient_address="Musterstraße 1, 12345 Musterstadt",
            student_name="Max Müller",
            student_class="5a",
            subject="Einladung Elternabend",
            content="Sehr geehrte Familie Müller...",
            teacher_name="Frau Schmidt"
        )

        assert request.recipient_name == "Familie Müller"
        assert request.student_name == "Max Müller"
        assert request.teacher_name == "Frau Schmidt"

    def test_create_full_request(self):
        """Test creating a request with all fields."""
        from letters_api import LetterCreateRequest, LetterType, LetterTone, SchoolInfoModel

        school_info = SchoolInfoModel(
            name="Musterschule",
            address="Schulweg 1, 12345 Musterstadt",
            phone="0123-456789",
            email="info@musterschule.de"
        )

        request = LetterCreateRequest(
            recipient_name="Familie Müller",
            recipient_address="Musterstraße 1, 12345 Musterstadt",
            student_name="Max Müller",
            student_class="5a",
            subject="Einladung Elternabend",
            content="Sehr geehrte Familie Müller...",
            teacher_name="Frau Schmidt",
            teacher_title="Klassenlehrerin",
            letter_type=LetterType.ELTERNABEND,
            tone=LetterTone.PROFESSIONAL,
            school_info=school_info,
            gfk_principles_applied=["Beobachtung", "Bitte"]
        )

        assert request.letter_type == LetterType.ELTERNABEND
        assert request.tone == LetterTone.PROFESSIONAL
        assert request.school_info.name == "Musterschule"


class TestHelperFunctions:
    """Tests für Helper-Funktionen."""

    def test_get_type_label(self):
        """Test type label function."""
        from letters_api import _get_type_label, LetterType

        assert "Einladung" in _get_type_label(LetterType.ELTERNABEND)
        assert "Fehlzeiten" in _get_type_label(LetterType.FEHLZEITEN)
        assert "Positives" in _get_type_label(LetterType.LOB)

    def test_get_tone_label(self):
        """Test tone label function."""
        from letters_api import _get_tone_label, LetterTone

        assert "förmlich" in _get_tone_label(LetterTone.FORMAL)
        assert "Professionell" in _get_tone_label(LetterTone.PROFESSIONAL)
        assert "Warmherzig" in _get_tone_label(LetterTone.WARM)


@pytest.mark.skipif(
    not WEASYPRINT_AVAILABLE,
    reason="WeasyPrint not available (requires system libraries)"
)
class TestLettersAPIEndpoints:
    """Integration tests für Letters API Endpoints."""

    @pytest.fixture
    def client(self):
        """Create test client."""
        try:
            from main import app
            return TestClient(app)
        except ImportError:
            pytest.skip("main.py not available for testing")

    @pytest.fixture
    def sample_letter_data(self):
        """Sample letter data for tests."""
        return {
            "recipient_name": "Familie Test",
            "recipient_address": "Teststraße 1\n12345 Teststadt",
            "student_name": "Test Kind",
            "student_class": "5a",
            "subject": "Testbrief",
            "content": "Dies ist ein Testbrief.",
            "teacher_name": "Herr Test",
            "letter_type": "general",
            "tone": "professional"
        }

    def test_create_letter(self, client, sample_letter_data):
        """Test creating a new letter."""
        if not client:
            pytest.skip("Client not available")

        response = client.post("/api/letters/", json=sample_letter_data)

        assert response.status_code == 200
        data = response.json()
        assert data["recipient_name"] == sample_letter_data["recipient_name"]
        assert data["student_name"] == sample_letter_data["student_name"]
        assert data["status"] == "draft"
        assert "id" in data

    def test_get_letter(self, client, sample_letter_data):
        """Test getting a letter by ID."""
        if not client:
            pytest.skip("Client not available")

        # First create a letter
        create_response = client.post("/api/letters/", json=sample_letter_data)
        letter_id = create_response.json()["id"]

        # Then get it
        response = client.get(f"/api/letters/{letter_id}")

        assert response.status_code == 200
        data = response.json()
        assert data["id"] == letter_id

    def test_update_letter(self, client, sample_letter_data):
        """Test updating a letter."""
        if not client:
            pytest.skip("Client not available")

        # Create letter
        create_response = client.post("/api/letters/", json=sample_letter_data)
        letter_id = create_response.json()["id"]

        # Update it
        update_data = {"subject": "Aktualisierter Betreff"}
        response = client.put(f"/api/letters/{letter_id}", json=update_data)

        assert response.status_code == 200
        data = response.json()
        assert data["subject"] == "Aktualisierter Betreff"

    def test_delete_letter(self, client, sample_letter_data):
        """Test deleting a letter."""
        if not client:
            pytest.skip("Client not available")

        # Create letter
        create_response = client.post("/api/letters/", json=sample_letter_data)
        letter_id = create_response.json()["id"]

        # Delete it
        response = client.delete(f"/api/letters/{letter_id}")
        assert response.status_code == 200

        # Verify it's deleted
        get_response = client.get(f"/api/letters/{letter_id}")
        assert get_response.status_code == 404

    def test_list_letters(self, client, sample_letter_data):
        """Test listing letters."""
        if not client:
            pytest.skip("Client not available")

        # Create a letter
        client.post("/api/letters/", json=sample_letter_data)

        # List all
        response = client.get("/api/letters/")

        assert response.status_code == 200
        data = response.json()
        assert "letters" in data
        assert "total" in data
        assert isinstance(data["letters"], list)

    def test_get_letter_types(self, client):
        """Test getting available letter types."""
        if not client:
            pytest.skip("Client not available")

        response = client.get("/api/letters/types")

        assert response.status_code == 200
        data = response.json()
        assert "types" in data
        assert len(data["types"]) > 0

    def test_get_letter_tones(self, client):
        """Test getting available tones."""
        if not client:
            pytest.skip("Client not available")

        response = client.get("/api/letters/tones")

        assert response.status_code == 200
        data = response.json()
        assert "tones" in data
        assert len(data["tones"]) > 0

    def test_export_pdf(self, client, sample_letter_data):
        """Test PDF export."""
        if not client:
            pytest.skip("Client not available")

        # Create letter
        create_response = client.post("/api/letters/", json=sample_letter_data)
        letter_id = create_response.json()["id"]

        # Export as PDF
        response = client.post(f"/api/letters/{letter_id}/export-pdf")

        assert response.status_code == 200
        assert response.headers["content-type"] == "application/pdf"
        assert b"%PDF" in response.content[:10]

    def test_export_pdf_direct(self, client, sample_letter_data):
        """Test direct PDF export without saving."""
        if not client:
            pytest.skip("Client not available")

        export_data = {"letter_data": sample_letter_data}
        response = client.post("/api/letters/export-pdf", json=export_data)

        assert response.status_code == 200
        assert response.headers["content-type"] == "application/pdf"

    def test_get_nonexistent_letter(self, client):
        """Test getting a letter that doesn't exist."""
        if not client:
            pytest.skip("Client not available")

        response = client.get("/api/letters/nonexistent-id")
        assert response.status_code == 404


class TestLetterImprove:
    """Tests für GFK-Verbesserungsvorschläge."""

    def test_improve_request_model(self):
        """Test ImproveRequest model."""
        from letters_api import ImproveRequest

        request = ImproveRequest(
            content="Der Schüler macht nie seine Hausaufgaben.",
            communication_type="behavior",
            tone="concerned"
        )

        assert request.content == "Der Schüler macht nie seine Hausaufgaben."
        assert request.communication_type == "behavior"

    def test_improve_response_model(self):
        """Test ImproveResponse model."""
        from letters_api import ImproveResponse

        response = ImproveResponse(
            improved_content="Ich habe beobachtet, dass die Hausaufgaben...",
            changes=["'nie' durch konkretes Datum ersetzt", "Ich-Botschaft verwendet"],
            gfk_score=0.85,
            gfk_principles_applied=["Beobachtung", "Gefühl", "Bedürfnis"]
        )

        assert response.gfk_score == 0.85
        assert "Beobachtung" in response.gfk_principles_applied


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