# tests/test_provision.py
import json
from unittest.mock import AsyncMock, MagicMock
from agentsh_secure_sandbox.core.types import ExecResult, SecureConfig
from agentsh_secure_sandbox.core.provision import provision, ProvisionResult, SECURITY_MODE_RANK


def _make_mock_adapter(exec_side_effects=None):
    """Create a mock adapter that returns configurable exec results."""
    adapter = MagicMock()
    adapter.write_file = AsyncMock()
    adapter.stop = AsyncMock()
    adapter.file_exists = AsyncMock(return_value=False)

    if exec_side_effects:
        adapter.exec = AsyncMock(side_effect=exec_side_effects)
    else:
        adapter.exec = AsyncMock(return_value=ExecResult(stdout="", stderr="", exit_code=0))
    return adapter


def test_security_mode_ranking():
    assert SECURITY_MODE_RANK["full"] > SECURITY_MODE_RANK["landlock"]
    assert SECURITY_MODE_RANK["landlock"] > SECURITY_MODE_RANK["landlock-only"]
    assert SECURITY_MODE_RANK["landlock-only"] > SECURITY_MODE_RANK["minimal"]


async def test_provision_running_strategy():
    """install_strategy='running' should skip provisioning entirely."""
    adapter = _make_mock_adapter()
    cfg = SecureConfig(install_strategy="running")
    result = await provision(adapter, cfg)
    assert result.passthrough is True
    assert isinstance(result.session_id, str)
    # Should not have called exec for binary installation
    # (may call for session creation)


async def test_provision_result_has_session_id():
    """Basic smoke test — provision returns a ProvisionResult."""
    detect_json = json.dumps({"security_mode": "full"})
    session_json = json.dumps({"session_id": "test-session-123"})

    def exec_side_effect(cmd, args=None, opts=None):
        full = f"{cmd} {' '.join(args or [])}"
        if "uname" in full:
            return ExecResult(stdout="x86_64", stderr="", exit_code=0)
        if "detect" in full:
            return ExecResult(stdout=detect_json, stderr="", exit_code=0)
        if "health" in full or "curl" in full and "18080" in full:
            return ExecResult(stdout="ok", stderr="", exit_code=0)
        if "session" in full and "create" in full:
            return ExecResult(stdout=session_json, stderr="", exit_code=0)
        return ExecResult(stdout="", stderr="", exit_code=0)

    adapter = _make_mock_adapter()
    adapter.exec = AsyncMock(side_effect=exec_side_effect)
    adapter.file_exists = AsyncMock(return_value=True)  # binary exists for preinstalled
    cfg = SecureConfig(install_strategy="preinstalled", skip_integrity_check=True)
    result = await provision(adapter, cfg)
    assert isinstance(result, ProvisionResult)
    assert isinstance(result.session_id, str)
    assert result.security_mode in ("full", "landlock", "landlock-only", "minimal")
