import pytest
from unittest.mock import patch, MagicMock
from httpx import AsyncClient
from sqlalchemy.ext.asyncio import AsyncSession
from src.group_settings.models import GroupConfig
from src.group_settings.repo import GroupConfigRepo
from src.core.encryption import decrypt

@pytest.fixture
async def sample_group(session: AsyncSession) -> GroupConfig:
    repo = GroupConfigRepo(session)
    return await repo.create_empty("test-group@example.com")

@pytest.mark.asyncio
async def test_get_settings_forbidden(auth_client: AsyncClient, sample_group: GroupConfig):
    """Test that a non-admin cannot access settings."""
    with patch("src.group_settings.router.check_user_in_group", return_value=False), \
         patch("src.group_settings.router.is_group_admin", return_value=False):
        response = await auth_client.get("/settings")
        assert response.status_code == 403

@pytest.mark.asyncio
async def test_update_settings_success(auth_client: AsyncClient, sample_group: GroupConfig, session: AsyncSession):
    """Test updating multiple setting fields as a group admin."""
    # Mock user as group admin
    with patch("src.group_settings.router.check_user_in_group", return_value=True), \
         patch("src.group_settings.router.is_group_admin", return_value=True), \
         patch("src.services.notification_service.send_test_email", return_value=None):
        
        payload = {
            "campflow_api_token": "secret-token",
            "email_account": "new@example.com",
            "smtp_server": "smtp.test.com",
            "smtp_port": 587,
            "auto_mail_recipient": "auto@example.com"
        }
        
        response = await auth_client.post("/settings", json=payload)
        assert response.status_code == 200
        data = response.json()
        
        assert data["email_account"] == "new@example.com"
        assert data["smtp_server"] == "smtp.test.com"
        assert data["smtp_port"] == 587
        assert data["auto_mail_recipient"] == "auto@example.com"
        assert data["has_campflow_token"] is True
        
        # Verify encryption in DB
        repo = GroupConfigRepo(session)
        config = await repo.get_by_group_email("test-group@example.com")
        assert config.email_account == "new@example.com"
        assert decrypt(config.campflow_api_token_enc) == "secret-token"

@pytest.mark.asyncio
async def test_super_admin_can_update_any_group(auth_client: AsyncClient, session: AsyncSession, db_user):
    """Test that a super-admin can update settings for a group they are not in."""
    # Set current user as super-admin
    db_user.is_admin = True
    await session.commit()
    
    # Create another group
    repo = GroupConfigRepo(session)
    other_group = await repo.create_empty("other-group@example.com")
    
    with patch("src.services.notification_service.send_test_email", return_value=None):
        payload = {
            "group_email": "other-group@example.com",
            "pdf_filename": "SuperAdminReport"
        }
        
        response = await auth_client.post("/settings", json=payload)
        assert response.status_code == 200
        assert response.json()["pdf_filename"] == "SuperAdminReport"

@pytest.mark.asyncio
async def test_update_partial_settings(auth_client: AsyncClient, sample_group: GroupConfig, session: AsyncSession):
    """Test that partial updates don't wipe existing fields."""
    repo = GroupConfigRepo(session)
    await repo.upsert(
        group_email=sample_group.group_email,
        email_account="original@example.com",
        smtp_server="smtp.original.com"
    )
    
    with patch("src.group_settings.router.check_user_in_group", return_value=True), \
         patch("src.group_settings.router.is_group_admin", return_value=True):
        payload = {
            "smtp_server": "smtp.new.com"
        }
        response = await auth_client.post("/settings", json=payload)
        assert response.status_code == 200
        data = response.json()
        
        assert data["email_account"] == "original@example.com"
        assert data["smtp_server"] == "smtp.new.com"
