# tests/integration/api/v1/admin/test_email_settings.py
"""Integration tests for admin email settings API."""

import pytest

from app.modules.tenancy.models import AdminSetting

# =============================================================================
# GET EMAIL STATUS TESTS
# =============================================================================


@pytest.mark.integration
@pytest.mark.email
class TestGetAdminEmailStatus:
    """Test suite for GET /admin/settings/email/status endpoint."""

    def test_get_status_unauthenticated(self, client):
        """Test getting status without auth fails."""
        response = client.get("/api/v1/admin/settings/email/status")
        assert response.status_code == 401

    def test_get_status_non_admin(self, client, auth_headers):
        """Test getting status as non-admin fails."""
        response = client.get(
            "/api/v1/admin/settings/email/status",
            headers=auth_headers,
        )
        assert response.status_code == 403

    def test_get_status_admin(self, client, admin_headers):
        """Test getting status as admin succeeds."""
        response = client.get(
            "/api/v1/admin/settings/email/status",
            headers=admin_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert "provider" in data
        assert "from_email" in data
        assert "enabled" in data
        assert "is_configured" in data

    def test_get_status_has_db_overrides_flag(self, client, admin_headers):
        """Test status includes has_db_overrides flag."""
        response = client.get(
            "/api/v1/admin/settings/email/status",
            headers=admin_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert "has_db_overrides" in data
        # Initially should be False (no DB settings)
        assert data["has_db_overrides"] is False


# =============================================================================
# UPDATE EMAIL SETTINGS TESTS
# =============================================================================


@pytest.mark.integration
@pytest.mark.email
class TestUpdateAdminEmailSettings:
    """Test suite for PUT /admin/settings/email/settings endpoint."""

    def test_update_unauthenticated(self, client):
        """Test updating settings without auth fails."""
        response = client.put(
            "/api/v1/admin/settings/email/settings",
            json={"from_email": "test@example.com"},
        )
        assert response.status_code == 401

    def test_update_non_admin(self, client, auth_headers):
        """Test updating settings as non-admin fails."""
        response = client.put(
            "/api/v1/admin/settings/email/settings",
            headers=auth_headers,
            json={"from_email": "test@example.com"},
        )
        assert response.status_code == 403

    def test_update_settings_admin(self, client, admin_headers, db):
        """Test updating settings as admin succeeds."""
        response = client.put(
            "/api/v1/admin/settings/email/settings",
            headers=admin_headers,
            json={
                "from_email": "platform@example.com",
                "from_name": "Test Platform",
                "provider": "smtp",
                "smtp_host": "smtp.test.com",
                "smtp_port": 587,
            },
        )

        assert response.status_code == 200
        data = response.json()
        assert data["success"] is True
        assert "updated_keys" in data
        assert "from_email" in data["updated_keys"]

        # Verify settings were stored in DB
        setting = (
            db.query(AdminSetting)
            .filter(AdminSetting.key == "email_from_address")
            .first()
        )
        assert setting is not None
        assert setting.value == "platform@example.com"

    def test_update_partial_settings(self, client, admin_headers):
        """Test updating only some settings."""
        response = client.put(
            "/api/v1/admin/settings/email/settings",
            headers=admin_headers,
            json={
                "enabled": False,
                "debug": True,
            },
        )

        assert response.status_code == 200
        data = response.json()
        assert data["success"] is True
        assert "enabled" in data["updated_keys"]
        assert "debug" in data["updated_keys"]

    def test_status_shows_db_overrides(self, client, admin_headers):
        """Test that status shows DB overrides after update."""
        # First, set a DB override
        client.put(
            "/api/v1/admin/settings/email/settings",
            headers=admin_headers,
            json={"from_email": "override@example.com"},
        )

        # Check status
        response = client.get(
            "/api/v1/admin/settings/email/status",
            headers=admin_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert data["has_db_overrides"] is True
        assert data["from_email"] == "override@example.com"


# =============================================================================
# RESET EMAIL SETTINGS TESTS
# =============================================================================


@pytest.mark.integration
@pytest.mark.email
class TestResetAdminEmailSettings:
    """Test suite for DELETE /admin/settings/email/settings endpoint."""

    def test_reset_unauthenticated(self, client):
        """Test resetting settings without auth fails."""
        response = client.delete("/api/v1/admin/settings/email/settings")
        assert response.status_code == 401

    def test_reset_non_admin(self, client, auth_headers):
        """Test resetting settings as non-admin fails."""
        response = client.delete(
            "/api/v1/admin/settings/email/settings",
            headers=auth_headers,
        )
        assert response.status_code == 403

    def test_reset_settings_admin(self, client, admin_headers, db):
        """Test resetting settings as admin."""
        # First, create some DB overrides
        client.put(
            "/api/v1/admin/settings/email/settings",
            headers=admin_headers,
            json={
                "from_email": "tobereset@example.com",
                "provider": "sendgrid",
            },
        )

        # Verify they exist
        setting = (
            db.query(AdminSetting)
            .filter(AdminSetting.key == "email_from_address")
            .first()
        )
        assert setting is not None

        # Reset
        response = client.delete(
            "/api/v1/admin/settings/email/settings",
            headers=admin_headers,
        )

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

        # Verify they're gone
        db.expire_all()
        setting = (
            db.query(AdminSetting)
            .filter(AdminSetting.key == "email_from_address")
            .first()
        )
        assert setting is None

    def test_status_after_reset(self, client, admin_headers):
        """Test status after reset shows no DB overrides."""
        # Set an override
        client.put(
            "/api/v1/admin/settings/email/settings",
            headers=admin_headers,
            json={"from_email": "override@example.com"},
        )

        # Reset
        client.delete(
            "/api/v1/admin/settings/email/settings",
            headers=admin_headers,
        )

        # Check status
        response = client.get(
            "/api/v1/admin/settings/email/status",
            headers=admin_headers,
        )

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


# =============================================================================
# TEST EMAIL TESTS
# =============================================================================


@pytest.mark.integration
@pytest.mark.email
class TestSendAdminTestEmail:
    """Test suite for POST /admin/settings/email/test endpoint."""

    def test_send_test_unauthenticated(self, client):
        """Test sending test email without auth fails."""
        response = client.post(
            "/api/v1/admin/settings/email/test",
            json={"to_email": "test@example.com"},
        )
        assert response.status_code == 401

    def test_send_test_non_admin(self, client, auth_headers):
        """Test sending test email as non-admin fails."""
        response = client.post(
            "/api/v1/admin/settings/email/test",
            headers=auth_headers,
            json={"to_email": "test@example.com"},
        )
        assert response.status_code == 403

    def test_send_test_invalid_email(self, client, admin_headers):
        """Test sending to invalid email format fails."""
        response = client.post(
            "/api/v1/admin/settings/email/test",
            headers=admin_headers,
            json={"to_email": "not-an-email"},
        )
        assert response.status_code == 422  # Validation error

    def test_send_test_admin(self, client, admin_headers):
        """Test sending test email as admin."""
        response = client.post(
            "/api/v1/admin/settings/email/test",
            headers=admin_headers,
            json={"to_email": "test@example.com"},
        )

        # May fail if email not configured, but should not be 401/403
        assert response.status_code in (200, 500)
        data = response.json()
        assert "success" in data
        assert "message" in data
