"""
Tests for Meeting Consent API

Tests for DSGVO-compliant consent management for meeting recordings.
"""

import pytest
from fastapi.testclient import TestClient
from fastapi import FastAPI

# Import the router
from meeting_consent_api import router as consent_router

app = FastAPI()
app.include_router(consent_router)
client = TestClient(app)


class TestConsentRequest:
    """Tests for requesting recording consent."""

    @pytest.fixture(autouse=True)
    def setup(self):
        """Clear consent store before each test."""
        from meeting_consent_api import _consent_store, _participant_consents
        _consent_store.clear()
        _participant_consents.clear()

    def test_request_consent_success(self):
        """Test requesting consent for a meeting."""
        response = client.post(
            "/api/meeting-consent/request",
            json={
                "meeting_id": "test-meeting-123",
                "consent_type": "opt_in",
                "participant_count": 3
            }
        )

        assert response.status_code == 200
        data = response.json()
        assert data["meeting_id"] == "test-meeting-123"
        assert data["consent_type"] == "opt_in"
        assert data["participant_count"] == 3
        assert data["all_consented"] is False
        assert data["can_record"] is False
        assert data["status"] == "pending"

    def test_request_consent_duplicate_rejected(self):
        """Test that duplicate consent requests are rejected."""
        # First request
        client.post(
            "/api/meeting-consent/request",
            json={"meeting_id": "dup-meeting", "consent_type": "opt_in"}
        )

        # Second request should fail
        response = client.post(
            "/api/meeting-consent/request",
            json={"meeting_id": "dup-meeting", "consent_type": "opt_in"}
        )

        assert response.status_code == 409
        assert "already exists" in response.json()["detail"]

    def test_request_consent_default_values(self):
        """Test consent request uses default values."""
        response = client.post(
            "/api/meeting-consent/request",
            json={"meeting_id": "default-meeting"}
        )

        assert response.status_code == 200
        data = response.json()
        assert data["consent_type"] == "opt_in"


class TestConsentStatus:
    """Tests for checking consent status."""

    @pytest.fixture(autouse=True)
    def setup(self):
        """Create test consent before each test."""
        from meeting_consent_api import _consent_store, _participant_consents
        _consent_store.clear()
        _participant_consents.clear()

        client.post(
            "/api/meeting-consent/request",
            json={
                "meeting_id": "status-test-meeting",
                "consent_type": "opt_in",
                "participant_count": 2
            }
        )

    def test_get_consent_status_existing(self):
        """Test getting status for existing consent."""
        response = client.get("/api/meeting-consent/status-test-meeting")

        assert response.status_code == 200
        data = response.json()
        assert data["meeting_id"] == "status-test-meeting"
        assert data["status"] == "pending"

    def test_get_consent_status_not_requested(self):
        """Test getting status for meeting without consent request."""
        response = client.get("/api/meeting-consent/nonexistent-meeting")

        assert response.status_code == 200
        data = response.json()
        assert data["status"] == "not_requested"
        assert data["can_record"] is False


class TestParticipantConsent:
    """Tests for recording individual participant consent."""

    @pytest.fixture(autouse=True)
    def setup(self):
        """Create test consent with 2 participants."""
        from meeting_consent_api import _consent_store, _participant_consents
        _consent_store.clear()
        _participant_consents.clear()

        client.post(
            "/api/meeting-consent/request",
            json={
                "meeting_id": "participant-test",
                "consent_type": "opt_in",
                "participant_count": 2
            }
        )

    def test_record_participant_consent_positive(self):
        """Test recording positive consent from participant."""
        response = client.post(
            "/api/meeting-consent/participant-test/participant",
            json={
                "participant_id": "user-1",
                "participant_name": "Alice",
                "consented": True
            }
        )

        assert response.status_code == 200
        data = response.json()
        assert data["consented_count"] == 1
        assert data["all_consented"] is False

    def test_record_participant_consent_negative(self):
        """Test recording negative consent from participant."""
        response = client.post(
            "/api/meeting-consent/participant-test/participant",
            json={
                "participant_id": "user-1",
                "consented": False
            }
        )

        assert response.status_code == 200
        data = response.json()
        assert data["consented"] is False

    def test_all_participants_consented_auto_approves(self):
        """Test that recording is approved when all participants consent."""
        # First participant
        client.post(
            "/api/meeting-consent/participant-test/participant",
            json={"participant_id": "user-1", "consented": True}
        )

        # Second participant (should trigger approval)
        response = client.post(
            "/api/meeting-consent/participant-test/participant",
            json={"participant_id": "user-2", "consented": True}
        )

        assert response.status_code == 200
        data = response.json()
        assert data["all_consented"] is True
        assert data["can_record"] is True

    def test_record_consent_meeting_not_found(self):
        """Test recording consent for non-existent meeting."""
        response = client.post(
            "/api/meeting-consent/nonexistent/participant",
            json={"participant_id": "user-1", "consented": True}
        )

        assert response.status_code == 404

    def test_update_existing_participant_consent(self):
        """Test updating consent for same participant."""
        # Initial consent
        client.post(
            "/api/meeting-consent/participant-test/participant",
            json={"participant_id": "user-1", "consented": True}
        )

        # Update to negative
        response = client.post(
            "/api/meeting-consent/participant-test/participant",
            json={"participant_id": "user-1", "consented": False}
        )

        assert response.status_code == 200
        data = response.json()
        assert data["consented"] is False


class TestConsentWithdrawal:
    """Tests for withdrawing consent."""

    @pytest.fixture(autouse=True)
    def setup(self):
        """Create approved consent."""
        from meeting_consent_api import _consent_store, _participant_consents
        _consent_store.clear()
        _participant_consents.clear()

        # Create and approve consent
        client.post(
            "/api/meeting-consent/request",
            json={
                "meeting_id": "withdraw-test",
                "consent_type": "opt_in",
                "participant_count": 1
            }
        )
        client.post(
            "/api/meeting-consent/withdraw-test/participant",
            json={"participant_id": "user-1", "consented": True}
        )

    def test_withdraw_consent(self):
        """Test withdrawing consent for a meeting."""
        response = client.post(
            "/api/meeting-consent/withdraw-test/withdraw",
            json={"reason": "Changed my mind"}
        )

        assert response.status_code == 200
        data = response.json()
        assert data["status"] == "withdrawn"

    def test_withdraw_consent_stops_recording_capability(self):
        """Test that withdrawal stops recording capability."""
        # Withdraw
        client.post(
            "/api/meeting-consent/withdraw-test/withdraw",
            json={}
        )

        # Check status
        response = client.get("/api/meeting-consent/withdraw-test")
        data = response.json()
        assert data["status"] == "withdrawn" or data["status"] == "not_requested"

    def test_withdraw_consent_not_found(self):
        """Test withdrawing consent for non-existent meeting."""
        response = client.post(
            "/api/meeting-consent/nonexistent/withdraw",
            json={}
        )

        assert response.status_code == 404


class TestAnnouncedRecording:
    """Tests for announced recording mode."""

    @pytest.fixture(autouse=True)
    def setup(self):
        """Clear store before each test."""
        from meeting_consent_api import _consent_store, _participant_consents
        _consent_store.clear()
        _participant_consents.clear()

    def test_announce_recording(self):
        """Test announcing a recording."""
        response = client.post(
            "/api/meeting-consent/announce?meeting_id=announced-meeting&announced_by=Teacher"
        )

        assert response.status_code == 200
        data = response.json()
        assert data["consent_type"] == "announced"
        assert data["can_record"] is True
        assert data["announced_by"] == "Teacher"

    def test_announce_recording_duplicate_rejected(self):
        """Test that duplicate announcements are rejected."""
        # First announcement
        client.post(
            "/api/meeting-consent/announce?meeting_id=dup-announce&announced_by=Teacher"
        )

        # Second announcement
        response = client.post(
            "/api/meeting-consent/announce?meeting_id=dup-announce&announced_by=Teacher"
        )

        assert response.status_code == 409


class TestParticipantsList:
    """Tests for listing participant consents."""

    @pytest.fixture(autouse=True)
    def setup(self):
        """Create test consent with participants."""
        from meeting_consent_api import _consent_store, _participant_consents
        _consent_store.clear()
        _participant_consents.clear()

        client.post(
            "/api/meeting-consent/request",
            json={"meeting_id": "list-test", "participant_count": 2}
        )
        client.post(
            "/api/meeting-consent/list-test/participant",
            json={"participant_id": "user-1-uuid-12345678", "consented": True}
        )
        client.post(
            "/api/meeting-consent/list-test/participant",
            json={"participant_id": "user-2-uuid-87654321", "consented": False}
        )

    def test_get_participants_list(self):
        """Test getting list of participant consents."""
        response = client.get("/api/meeting-consent/list-test/participants")

        assert response.status_code == 200
        data = response.json()
        assert len(data["participants"]) == 2

    def test_participants_list_anonymized(self):
        """Test that participant IDs are anonymized."""
        response = client.get("/api/meeting-consent/list-test/participants")
        data = response.json()

        # IDs should be truncated to last 8 chars
        for p in data["participants"]:
            assert len(p["participant_id"]) == 8


class TestHealthCheck:
    """Tests for health check endpoint."""

    def test_health_check(self):
        """Test health check returns healthy status."""
        response = client.get("/api/meeting-consent/health")

        assert response.status_code == 200
        data = response.json()
        assert data["status"] == "healthy"
