import asyncio
from uuid import UUID
import pytest
from unittest.mock import MagicMock

from app.core.tenant_context import (
    set_current_account_id,
    clear_current_account_id,
    get_current_account_id,
)


def test_contextvar_is_none_by_default():
    assert get_current_account_id() is None


def test_set_and_clear():
    account_id = UUID("aaaaaaaa-0000-0000-0000-000000000001")
    token = set_current_account_id(account_id)
    assert get_current_account_id() == str(account_id)
    clear_current_account_id(token)
    assert get_current_account_id() is None


def test_tasks_are_isolated():
    """Each asyncio task has its own ContextVar value."""
    results = {}

    async def set_in_task(name: str, value: str):
        token = set_current_account_id(UUID(value))
        await asyncio.sleep(0)
        results[name] = get_current_account_id()
        clear_current_account_id(token)

    async def run():
        await asyncio.gather(
            set_in_task("a", "aaaaaaaa-0000-0000-0000-000000000001"),
            set_in_task("b", "bbbbbbbb-0000-0000-0000-000000000002"),
        )

    asyncio.run(run())
    assert results["a"] == "aaaaaaaa-0000-0000-0000-000000000001"
    assert results["b"] == "bbbbbbbb-0000-0000-0000-000000000002"


@pytest.mark.asyncio
async def test_require_tenant_context_raises_403_when_no_account():
    from fastapi import HTTPException
    from app.api.deps import require_tenant_context

    user = MagicMock()
    user.account_id = None

    gen = require_tenant_context(current_user=user)
    with pytest.raises(HTTPException) as exc_info:
        await gen.__anext__()
    assert exc_info.value.status_code == 403
    assert "account required" in exc_info.value.detail.lower()
