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

import pytest
from datetime import datetime, timezone

from app.modules.messaging.models import VendorEmailSettings


# =============================================================================
# FIXTURES
# =============================================================================


@pytest.fixture
def vendor_email_settings(db, test_vendor_with_vendor_user):
    """Create email settings for vendor owned by test vendor user."""
    settings = VendorEmailSettings(
        vendor_id=test_vendor_with_vendor_user.id,
        from_email="vendor@example.com",
        from_name="Vendor Test",
        provider="smtp",
        smtp_host="smtp.example.com",
        smtp_port=587,
        smtp_username="vendoruser",
        smtp_password="vendorpass",
        smtp_use_tls=True,
        is_configured=True,
        is_verified=False,
    )
    db.add(settings)
    db.commit()
    db.refresh(settings)
    return settings


@pytest.fixture
def verified_vendor_email_settings(db, test_vendor_with_vendor_user):
    """Create verified email settings."""
    settings = VendorEmailSettings(
        vendor_id=test_vendor_with_vendor_user.id,
        from_email="verified@example.com",
        from_name="Verified Sender",
        provider="smtp",
        smtp_host="smtp.example.com",
        smtp_port=587,
        smtp_username="testuser",
        smtp_password="testpass",
        smtp_use_tls=True,
        is_configured=True,
        is_verified=True,
        last_verified_at=datetime.now(timezone.utc),
    )
    db.add(settings)
    db.commit()
    db.refresh(settings)
    return settings


# =============================================================================
# GET EMAIL SETTINGS TESTS
# =============================================================================


@pytest.mark.integration
@pytest.mark.email
class TestGetEmailSettings:
    """Test suite for GET /email-settings endpoint."""

    def test_get_settings_not_configured(
        self, client, vendor_auth_headers, test_vendor_with_vendor_user
    ):
        """Test getting settings when not configured."""
        response = client.get(
            "/api/v1/vendor/email-settings",
            headers=vendor_auth_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert data["configured"] is False
        assert data["settings"] is None

    def test_get_settings_configured(
        self, client, vendor_auth_headers, vendor_email_settings
    ):
        """Test getting configured settings."""
        response = client.get(
            "/api/v1/vendor/email-settings",
            headers=vendor_auth_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert data["configured"] is True
        assert data["settings"]["from_email"] == "vendor@example.com"
        # Password should be masked
        assert "vendorpass" not in str(data)

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


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


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

    def test_get_status_not_configured(
        self, client, vendor_auth_headers, test_vendor_with_vendor_user
    ):
        """Test status when not configured."""
        response = client.get(
            "/api/v1/vendor/email-settings/status",
            headers=vendor_auth_headers,
        )

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

    def test_get_status_configured_unverified(
        self, client, vendor_auth_headers, vendor_email_settings
    ):
        """Test status when configured but not verified."""
        response = client.get(
            "/api/v1/vendor/email-settings/status",
            headers=vendor_auth_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert data["is_configured"] is True
        assert data["is_verified"] is False

    def test_get_status_verified(
        self, client, vendor_auth_headers, verified_vendor_email_settings
    ):
        """Test status when verified."""
        response = client.get(
            "/api/v1/vendor/email-settings/status",
            headers=vendor_auth_headers,
        )

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


# =============================================================================
# GET PROVIDERS TESTS
# =============================================================================


@pytest.mark.integration
@pytest.mark.email
class TestGetProviders:
    """Test suite for GET /email-settings/providers endpoint."""

    def test_get_providers(self, client, vendor_auth_headers):
        """Test getting available providers."""
        response = client.get(
            "/api/v1/vendor/email-settings/providers",
            headers=vendor_auth_headers,
        )

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

        # SMTP should always be available
        smtp = next((p for p in data["providers"] if p["code"] == "smtp"), None)
        assert smtp is not None
        assert smtp["available"] is True


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


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

    def test_create_settings(
        self, client, vendor_auth_headers, test_vendor_with_vendor_user
    ):
        """Test creating new email settings."""
        response = client.put(
            "/api/v1/vendor/email-settings",
            headers=vendor_auth_headers,
            json={
                "from_email": "new@example.com",
                "from_name": "New Vendor",
                "provider": "smtp",
                "smtp_host": "smtp.example.com",
                "smtp_port": 587,
                "smtp_username": "user",
                "smtp_password": "pass",
                "smtp_use_tls": True,
            },
        )

        assert response.status_code == 200
        data = response.json()
        assert data["success"] is True
        assert data["settings"]["from_email"] == "new@example.com"

    def test_update_existing_settings(
        self, client, vendor_auth_headers, vendor_email_settings
    ):
        """Test updating existing settings."""
        response = client.put(
            "/api/v1/vendor/email-settings",
            headers=vendor_auth_headers,
            json={
                "from_email": "updated@example.com",
                "from_name": "Updated Name",
                "provider": "smtp",
            },
        )

        assert response.status_code == 200
        data = response.json()
        assert data["settings"]["from_email"] == "updated@example.com"
        assert data["settings"]["from_name"] == "Updated Name"

    def test_premium_provider_rejected_for_basic_tier(
        self, client, vendor_auth_headers, test_vendor_with_vendor_user
    ):
        """Test premium provider rejected without Business tier."""
        response = client.put(
            "/api/v1/vendor/email-settings",
            headers=vendor_auth_headers,
            json={
                "from_email": "test@example.com",
                "from_name": "Test",
                "provider": "sendgrid",
                "sendgrid_api_key": "test-key",
            },
        )

        # Should fail with 403 (AuthorizationException)
        assert response.status_code == 403

    def test_invalid_email_rejected(self, client, vendor_auth_headers):
        """Test invalid email format rejected."""
        response = client.put(
            "/api/v1/vendor/email-settings",
            headers=vendor_auth_headers,
            json={
                "from_email": "not-an-email",
                "from_name": "Test",
            },
        )

        assert response.status_code == 422  # Validation error


# =============================================================================
# DELETE EMAIL SETTINGS TESTS
# =============================================================================


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

    def test_delete_settings(
        self, client, vendor_auth_headers, vendor_email_settings, db
    ):
        """Test deleting email settings."""
        response = client.delete(
            "/api/v1/vendor/email-settings",
            headers=vendor_auth_headers,
        )

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

        # Verify deletion
        settings = (
            db.query(VendorEmailSettings)
            .filter(VendorEmailSettings.vendor_id == vendor_email_settings.vendor_id)
            .first()
        )
        assert settings is None

    def test_delete_settings_not_found(
        self, client, vendor_auth_headers, test_vendor_with_vendor_user
    ):
        """Test deleting non-existent settings returns 404."""
        response = client.delete(
            "/api/v1/vendor/email-settings",
            headers=vendor_auth_headers,
        )

        assert response.status_code == 404


# =============================================================================
# VERIFY EMAIL SETTINGS TESTS
# =============================================================================


@pytest.mark.integration
@pytest.mark.email
class TestVerifyEmailSettings:
    """Test suite for POST /email-settings/verify endpoint."""

    def test_verify_not_configured(
        self, client, vendor_auth_headers, test_vendor_with_vendor_user
    ):
        """Test verification fails when settings not configured."""
        response = client.post(
            "/api/v1/vendor/email-settings/verify",
            headers=vendor_auth_headers,
            json={"test_email": "test@example.com"},
        )

        assert response.status_code == 404

    def test_verify_invalid_email(
        self, client, vendor_auth_headers, vendor_email_settings
    ):
        """Test verification with invalid email address."""
        response = client.post(
            "/api/v1/vendor/email-settings/verify",
            headers=vendor_auth_headers,
            json={"test_email": "not-an-email"},
        )

        assert response.status_code == 422  # Validation error
