from datetime import datetime, timezone
from types import SimpleNamespace
from uuid import uuid4

import pytest

from src.domain.cloud_infra.models import WorkspaceCloudAssignmentStatus
from src.domain.cloud_infra.schemas import AssignWorkspaceRequest
from src.domain.cloud_infra.service import CloudInfraService


@pytest.mark.asyncio
async def test_assign_workspace_reassigns_existing_row_and_account_counts(monkeypatch) -> None:
    workspace_id = uuid4()
    old_instance_id = uuid4()
    new_instance_id = uuid4()
    old_account_id = uuid4()
    new_account_id = uuid4()
    existing = SimpleNamespace(
        id=uuid4(),
        workspace_id=workspace_id,
        cloud_instance_id=old_instance_id,
        status=WorkspaceCloudAssignmentStatus.active,
        assigned_at=datetime.now(timezone.utc),
        released_at=None,
    )
    old_instance = SimpleNamespace(id=old_instance_id, cf_account_id=old_account_id)
    new_instance = SimpleNamespace(id=new_instance_id, cf_account_id=new_account_id)
    reassigned = []
    count_updates = []

    class Assignments:
        async def get_active_for_workspace(self, value):
            assert value == workspace_id
            return existing

        async def reassign(self, row, *, cloud_instance_id):
            row.cloud_instance_id = cloud_instance_id
            row.assigned_at = datetime.now(timezone.utc)
            reassigned.append(row)
            return row

    class Instances:
        async def get_by_id(self, value):
            return {old_instance_id: old_instance, new_instance_id: new_instance}[value]

    class Accounts:
        async def increment_workspace_count(self, account_id, delta=1):
            count_updates.append((account_id, delta))

    service = CloudInfraService(
        cf_account_repo=Accounts(),
        instance_repo=Instances(),
        assignment_repo=Assignments(),
    )
    monkeypatch.setattr(
        "src.domain.cloud_infra.service._creds_cache",
        {f"ws:{workspace_id}": (object(), 0.0)},
    )

    result = await service.assign_workspace(
        workspace_id,
        AssignWorkspaceRequest(cloud_instance_id=new_instance_id),
    )

    assert result.cloud_instance_id == new_instance_id
    assert reassigned == [existing]
    assert count_updates == [(old_account_id, -1), (new_account_id, 1)]
    assert existing.status == WorkspaceCloudAssignmentStatus.active
    assert f"ws:{workspace_id}" not in __import__(
        "src.domain.cloud_infra.service", fromlist=["_creds_cache"]
    )._creds_cache
