import uuid
from types import SimpleNamespace
from unittest.mock import AsyncMock

import pytest

from domains.groups.models import GroupMemberRole, GroupType
from domains.groups import service


@pytest.mark.asyncio
async def test_create_user_group_creates_private_group_and_owner_membership(monkeypatch):
    created_group = None
    added_membership = None

    async def fake_create_group(db, group):
        nonlocal created_group
        created_group = group
        group.id = uuid.uuid4()
        return group

    async def fake_add_group_member(db, membership):
        nonlocal added_membership
        added_membership = membership
        return membership

    monkeypatch.setattr(service, "create_group", fake_create_group)
    monkeypatch.setattr(service, "add_group_member", fake_add_group_member)

    owner_id = uuid.uuid4()
    group = await service.create_user_group(object(), "team-alpha", owner_id)

    assert group.type == GroupType.PRIVATE
    assert group.owner_id == owner_id
    assert created_group is group
    assert added_membership is not None
    assert added_membership.user_id == owner_id
    assert added_membership.role == GroupMemberRole.MANAGER


@pytest.mark.asyncio
async def test_create_admin_group_creates_public_group_without_membership(monkeypatch):
    create_group_mock = AsyncMock(side_effect=lambda db, group: setattr(group, "id", uuid.uuid4()) or group)
    add_group_member_mock = AsyncMock()

    monkeypatch.setattr(service, "create_group", create_group_mock)
    monkeypatch.setattr(service, "add_group_member", add_group_member_mock)

    owner_id = uuid.uuid4()
    group = await service.create_admin_group(object(), "ops-room", owner_id)

    assert group.type == GroupType.PUBLIC
    assert group.owner_id == owner_id
    add_group_member_mock.assert_not_awaited()


@pytest.mark.asyncio
async def test_list_group_members_api_returns_only_real_members(monkeypatch):
    group_id = uuid.uuid4()
    member_id = uuid.uuid4()
    members_data = [
        (
            SimpleNamespace(
                user_id=member_id,
                role=GroupMemberRole.MEMBER,
            ),
            "neda-user",
        )
    ]

    monkeypatch.setattr(
        service,
        "get_group_members_with_details",
        AsyncMock(return_value=members_data),
    )
    monkeypatch.setattr(
        service,
        "list_online_users",
        AsyncMock(return_value=[str(member_id)]),
    )

    response = await service.list_group_members_api(object(), group_id)

    assert response == [
        {
            "user_id": member_id,
            "username": "neda-user",
            "role": GroupMemberRole.MEMBER,
            "is_online": True,
        }
    ]


def test_group_routes_are_namespaced():
    from main import app

    route_map = {
        (route.path, method)
        for route in app.routes
        if getattr(route, "methods", None)
        for method in route.methods
    }

    assert ("/groups/", "POST") in route_map
    assert ("/admin/groups/", "POST") in route_map
    assert ("/admin/groups/", "GET") in route_map
    assert ("/admin/groups/{group_id}/members", "GET") in route_map
    assert ("/admin/groups/{group_id}/members", "POST") in route_map
