"""
Integration Tests für LibreChat + Tavily Web Search.

Diese Tests prüfen:
1. Tavily API Konnektivität
2. LibreChat Container Health
3. End-to-End Web Search Flow
"""

import os
import pytest
import httpx
from unittest.mock import patch, AsyncMock

# Test-Konfiguration
TAVILY_API_KEY = os.getenv("TAVILY_API_KEY", "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")
LIBRECHAT_URL = os.getenv("LIBRECHAT_URL", "http://localhost:3080")
TAVILY_API_URL = "https://api.tavily.com"


class TestTavilyAPIConnectivity:
    """Tests für direkte Tavily API Verbindung."""

    @pytest.mark.asyncio
    async def test_tavily_api_health(self):
        """Test: Tavily API ist erreichbar und antwortet."""
        async with httpx.AsyncClient(timeout=30.0) as client:
            response = await client.post(
                f"{TAVILY_API_URL}/search",
                json={
                    "api_key": TAVILY_API_KEY,
                    "query": "test query",
                    "max_results": 1
                }
            )

            assert response.status_code == 200
            data = response.json()
            assert "results" in data
            assert "query" in data

    @pytest.mark.asyncio
    async def test_tavily_search_returns_results(self):
        """Test: Tavily gibt Suchergebnisse zurück."""
        async with httpx.AsyncClient(timeout=30.0) as client:
            response = await client.post(
                f"{TAVILY_API_URL}/search",
                json={
                    "api_key": TAVILY_API_KEY,
                    "query": "LibreChat AI chat platform",
                    "max_results": 3
                }
            )

            assert response.status_code == 200
            data = response.json()

            # Prüfe Struktur
            assert "results" in data
            assert len(data["results"]) > 0

            # Prüfe erstes Ergebnis
            first_result = data["results"][0]
            assert "url" in first_result
            assert "title" in first_result
            assert "content" in first_result
            assert "score" in first_result

    @pytest.mark.asyncio
    async def test_tavily_invalid_api_key(self):
        """Test: Tavily gibt Fehler bei ungültigem API Key."""
        async with httpx.AsyncClient(timeout=30.0) as client:
            response = await client.post(
                f"{TAVILY_API_URL}/search",
                json={
                    "api_key": "invalid-key-12345",
                    "query": "test",
                    "max_results": 1
                }
            )

            # Sollte 401 oder 403 zurückgeben
            assert response.status_code in [401, 403, 400]

    @pytest.mark.asyncio
    async def test_tavily_search_depth_basic(self):
        """Test: Tavily basic search depth funktioniert."""
        async with httpx.AsyncClient(timeout=30.0) as client:
            response = await client.post(
                f"{TAVILY_API_URL}/search",
                json={
                    "api_key": TAVILY_API_KEY,
                    "query": "Python programming",
                    "search_depth": "basic",
                    "max_results": 2
                }
            )

            assert response.status_code == 200
            data = response.json()
            assert "response_time" in data

    @pytest.mark.asyncio
    async def test_tavily_german_query(self):
        """Test: Tavily kann deutsche Suchanfragen verarbeiten."""
        async with httpx.AsyncClient(timeout=30.0) as client:
            response = await client.post(
                f"{TAVILY_API_URL}/search",
                json={
                    "api_key": TAVILY_API_KEY,
                    "query": "Datenschutz Schulen Deutschland",
                    "max_results": 3
                }
            )

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


class TestLibreChatHealth:
    """Tests für LibreChat Container Health."""

    @pytest.mark.asyncio
    async def test_librechat_api_health(self):
        """Test: LibreChat API ist erreichbar."""
        async with httpx.AsyncClient(timeout=10.0) as client:
            try:
                response = await client.get(f"{LIBRECHAT_URL}/api/health")
                # LibreChat hat keinen /api/health, aber / sollte funktionieren
                if response.status_code == 404:
                    response = await client.get(f"{LIBRECHAT_URL}/")

                assert response.status_code in [200, 301, 302]
            except httpx.ConnectError:
                pytest.skip("LibreChat Container nicht erreichbar")

    @pytest.mark.asyncio
    async def test_librechat_frontend_loads(self):
        """Test: LibreChat Frontend lädt."""
        async with httpx.AsyncClient(timeout=10.0) as client:
            try:
                response = await client.get(f"{LIBRECHAT_URL}/")

                assert response.status_code in [200, 301, 302]
                # Prüfe ob HTML zurückkommt
                if response.status_code == 200:
                    assert "html" in response.headers.get("content-type", "").lower() or \
                           "<!DOCTYPE" in response.text[:100]
            except httpx.ConnectError:
                pytest.skip("LibreChat Container nicht erreichbar")


class TestTavilyConfigValidation:
    """Tests für Tavily Konfigurationsvalidierung."""

    def test_tavily_api_key_format(self):
        """Test: Tavily API Key hat korrektes Format."""
        # Tavily Keys beginnen mit "tvly-"
        assert TAVILY_API_KEY.startswith("tvly-"), \
            f"Tavily API Key sollte mit 'tvly-' beginnen, ist aber: {TAVILY_API_KEY[:10]}..."

    def test_tavily_api_key_length(self):
        """Test: Tavily API Key hat korrekte Länge."""
        # Tavily Keys sind typischerweise ~40 Zeichen
        assert len(TAVILY_API_KEY) > 30, \
            f"Tavily API Key zu kurz: {len(TAVILY_API_KEY)} Zeichen"

    def test_tavily_api_key_not_placeholder(self):
        """Test: Tavily API Key ist kein Platzhalter."""
        placeholders = [
            "your-tavily-api-key",
            "TAVILY_API_KEY",
            "tvly-xxx",
            "tvly-placeholder",
        ]
        assert TAVILY_API_KEY not in placeholders, \
            "Tavily API Key ist noch ein Platzhalter"


class TestBreakPilotTavilyIntegration:
    """Tests für BreakPilot Backend Tavily Integration."""

    @pytest.mark.asyncio
    async def test_breakpilot_tool_gateway_available(self):
        """Test: BreakPilot Tool Gateway ist verfügbar."""
        from llm_gateway.services.tool_gateway import ToolGateway, ToolGatewayConfig

        config = ToolGatewayConfig(tavily_api_key=TAVILY_API_KEY)
        gateway = ToolGateway(config)

        assert gateway.tavily_available is True

    @pytest.mark.asyncio
    async def test_breakpilot_pii_redaction_before_tavily(self):
        """Test: PII wird vor Tavily-Anfragen redaktiert."""
        from llm_gateway.services.pii_detector import PIIDetector

        detector = PIIDetector()

        # Text mit PII
        query_with_pii = "Suche Informationen über max.mustermann@schule.de in Klasse 5a"

        result = detector.redact(query_with_pii)

        # PII sollte redaktiert sein
        assert "max.mustermann@schule.de" not in result.redacted_text
        assert result.pii_found is True
        assert len(result.matches) > 0
        # E-Mail sollte als [EMAIL_REDACTED] redaktiert sein
        assert "[EMAIL_REDACTED]" in result.redacted_text

    @pytest.mark.asyncio
    async def test_breakpilot_tavily_search_with_pii_protection(self):
        """Test: Tavily Search mit PII-Schutz funktioniert."""
        from llm_gateway.services.tool_gateway import ToolGateway, ToolGatewayConfig

        config = ToolGatewayConfig(tavily_api_key=TAVILY_API_KEY)
        gateway = ToolGateway(config)

        # Suche mit PII (wird automatisch redaktiert)
        result = await gateway.search(
            query="Datenschutz Email hans.mueller@example.com",
            max_results=2
        )

        # Wichtig: PII-Schutz hat funktioniert
        assert result is not None
        assert result.pii_detected is True
        assert "email" in result.pii_types
        assert result.redacted_query is not None
        assert "hans.mueller@example.com" not in result.redacted_query
        assert "[EMAIL_REDACTED]" in result.redacted_query
        # Ergebnisse sind optional - die redaktierte Query kann leer sein
        assert result.results is not None  # Liste existiert (kann leer sein)


class TestEndToEndFlow:
    """End-to-End Tests für den kompletten Flow."""

    @pytest.mark.asyncio
    async def test_complete_search_flow(self):
        """Test: Kompletter Such-Flow von Anfrage bis Ergebnis."""
        # 1. Tavily API direkt
        async with httpx.AsyncClient(timeout=30.0) as client:
            response = await client.post(
                f"{TAVILY_API_URL}/search",
                json={
                    "api_key": TAVILY_API_KEY,
                    "query": "Schulrecht Deutschland aktuelle Änderungen",
                    "max_results": 3,
                    "search_depth": "basic"
                }
            )

            assert response.status_code == 200
            data = response.json()

            # Validiere Ergebnisse
            assert len(data["results"]) > 0

            for result in data["results"]:
                assert "url" in result
                assert "title" in result
                assert result["url"].startswith("http")

    @pytest.mark.asyncio
    async def test_search_response_time(self):
        """Test: Tavily antwortet in akzeptabler Zeit."""
        import time

        async with httpx.AsyncClient(timeout=30.0) as client:
            start = time.time()

            response = await client.post(
                f"{TAVILY_API_URL}/search",
                json={
                    "api_key": TAVILY_API_KEY,
                    "query": "test query",
                    "max_results": 3
                }
            )

            elapsed = time.time() - start

            assert response.status_code == 200
            # Sollte unter 10 Sekunden antworten
            assert elapsed < 10.0, f"Tavily Antwortzeit zu lang: {elapsed:.2f}s"


# Fixtures für gemeinsame Test-Ressourcen
@pytest.fixture
def tavily_api_key():
    """Fixture für Tavily API Key."""
    return TAVILY_API_KEY


@pytest.fixture
def librechat_url():
    """Fixture für LibreChat URL."""
    return LIBRECHAT_URL
