from types import SimpleNamespace
from unittest.mock import AsyncMock, MagicMock

import pytest

from src.core.errors import ValidationException
from src.domain.schemas import UserUpdate
from src.services.user_service import UserService


@pytest.mark.asyncio
async def test_update_user_clears_ssp_links_on_dfip_to_rf_role_change():
    db = AsyncMock()
    service = UserService(db)
    service.user_repo = MagicMock()
    service.user_repo.get = AsyncMock(
        return_value=SimpleNamespace(
            id=10,
            username="target",
            role_id=2,
        )
    )
    service.user_repo.get_by_username = AsyncMock(return_value=None)
    service.user_repo.update = AsyncMock(
        return_value=SimpleNamespace(id=10, role_id=3, username="target")
    )
    service.user_repo.clear_many_ssp = AsyncMock(return_value=True)

    admin = SimpleNamespace(id=1, role_id=1)
    await service.update_user(10, UserUpdate(role_id=3), admin)

    service.user_repo.clear_many_ssp.assert_awaited_once_with(10)


@pytest.mark.asyncio
async def test_update_user_prevents_self_role_change():
    db = AsyncMock()
    service = UserService(db)
    service.user_repo = MagicMock()
    service.user_repo.get = AsyncMock(
        return_value=SimpleNamespace(
            id=1,
            username="admin",
            role_id=1,
        )
    )
    service.user_repo.get_by_username = AsyncMock(return_value=None)

    admin = SimpleNamespace(id=1, role_id=1)
    with pytest.raises(ValidationException):
        await service.update_user(1, UserUpdate(role_id=2), admin)


@pytest.mark.asyncio
async def test_set_many_ssp_blocks_multiple_links_for_rf():
    db = AsyncMock()
    service = UserService(db)
    service.user_repo = MagicMock()
    service.user_repo.get = AsyncMock(return_value=SimpleNamespace(id=7, role_id=3))
    service.user_repo.get_many_ssp_ids = AsyncMock(return_value=[1])

    admin = SimpleNamespace(id=1, role_id=1)
    with pytest.raises(ValidationException):
        await service.set_many_ssp(7, [2], admin)
