"""Unit tests for terminal container-user resolution."""

from unittest.mock import AsyncMock, MagicMock

import pytest

from src.api.system.terminal import _resolve_container_user


@pytest.mark.unit
async def test_resolve_container_user_legacy_tool_type():
    """Legacy tools have no manifest user."""
    tool_type = MagicMock()
    tool_type.definition_type = "legacy"
    tool_type.manifest_id = None

    instance = MagicMock()
    instance.tool_type_id = "tool-type-uuid"

    session = AsyncMock()
    session.get = AsyncMock(return_value=tool_type)

    result = await _resolve_container_user(session, instance)

    assert result is None
    session.get.assert_awaited_once()


@pytest.mark.unit
async def test_resolve_container_user_manifest_no_manifest_id():
    """Manifest-based tools without a manifest_id return None."""
    tool_type = MagicMock()
    tool_type.definition_type = "manifest"
    tool_type.manifest_id = None

    instance = MagicMock()
    instance.tool_type_id = "tool-type-uuid"

    session = AsyncMock()
    session.get = AsyncMock(return_value=tool_type)

    result = await _resolve_container_user(session, instance)

    assert result is None


@pytest.mark.unit
async def test_resolve_container_user_manifest_with_user():
    """Manifest-based tools resolve the declared container user."""
    manifest_id = "manifest-uuid"

    tool_type = MagicMock()
    tool_type.definition_type = "manifest"
    tool_type.manifest_id = manifest_id

    manifest_def = MagicMock()
    manifest_def.manifest = {"user": {"name": "dev", "uid": 1000, "gid": 1000}}
    manifest_def.base_definition_id = None

    instance = MagicMock()
    instance.tool_type_id = "tool-type-uuid"

    session = AsyncMock()

    async def session_get(model, obj_id):
        if obj_id == "tool-type-uuid":
            return tool_type
        if obj_id == manifest_id:
            return manifest_def
        return None

    session.get.side_effect = session_get

    result = await _resolve_container_user(session, instance)

    assert result == "dev"


@pytest.mark.unit
async def test_resolve_container_user_manifest_with_base_definition():
    """Base-definition users are inherited and overridden by tool manifests."""
    base_id = "base-uuid"
    manifest_id = "manifest-uuid"

    tool_type = MagicMock()
    tool_type.definition_type = "manifest"
    tool_type.manifest_id = manifest_id

    manifest_def = MagicMock()
    manifest_def.manifest = {"user": {"name": "override", "uid": 1001, "gid": 1001}}
    manifest_def.base_definition_id = base_id

    base_def = MagicMock()
    base_def.manifest = {
        "base_image": "ubuntu:24.04",
        "user": {"name": "base", "uid": 1000, "gid": 1000},
    }

    instance = MagicMock()
    instance.tool_type_id = "tool-type-uuid"

    session = AsyncMock()

    async def session_get(model, obj_id):
        if obj_id == "tool-type-uuid":
            return tool_type
        if obj_id == manifest_id:
            return manifest_def
        if obj_id == base_id:
            return base_def
        return None

    session.get.side_effect = session_get

    result = await _resolve_container_user(session, instance)

    assert result == "override"


@pytest.mark.unit
async def test_resolve_container_user_missing_manifest_definition():
    """A manifest_id pointing to a missing definition returns None."""
    manifest_id = "manifest-uuid"

    tool_type = MagicMock()
    tool_type.definition_type = "manifest"
    tool_type.manifest_id = manifest_id

    instance = MagicMock()
    instance.tool_type_id = "tool-type-uuid"

    session = AsyncMock()

    async def session_get(model, obj_id):
        if obj_id == "tool-type-uuid":
            return tool_type
        return None

    session.get.side_effect = session_get

    result = await _resolve_container_user(session, instance)

    assert result is None
