from __future__ import annotations

import pytest
import respx

from omni import OmniClient
from omni.client import configure, get_sync_client, use_instance


def _config(url: str = "https://omni.example") -> dict:
    return {
        "default_instance": "default",
        "instances": {
            "default": {
                "url": url,
            },
            "other": {
                "url": "https://other.example",
            },
        },
    }


def test_singleton_returns_same_client_for_same_context() -> None:
    configure(config=_config())
    c1 = get_sync_client()
    c2 = get_sync_client()
    assert c1 is c2


def test_singleton_context_switch_changes_client_key() -> None:
    configure(config=_config())
    c1 = get_sync_client()
    with use_instance("other"):
        c2 = get_sync_client()
    assert c1 is not c2


def test_unified_client_sync_method() -> None:
    with respx.mock(base_url="https://omni.example") as mock:
        mock.post("/api/omni.resources.ResourceService/Get").respond(
            json={"body": '{"metadata":{"id":"cluster-a"}}'}
        )

        client = OmniClient(config=_config())
        sync_payload = client.get_cluster("cluster-a")
        assert "body" in sync_payload
        client.close()


def test_unified_client_close_after_sync_call() -> None:
    with respx.mock(base_url="https://omni.example") as mock:
        mock.post("/api/omni.resources.ResourceService/Get").respond(
            json={"body": '{"metadata":{"id":"cluster-a"}}'}
        )

        client = OmniClient(config=_config())
        client.get_cluster("cluster-a")
        client.close()
        client.close()


@pytest.mark.asyncio()
async def test_unified_client_async_method() -> None:
    with respx.mock(base_url="https://omni.example") as mock:
        mock.post("/api/omni.resources.ResourceService/Get").respond(
            json={"body": '{"metadata":{"id":"cluster-a"}}'}
        )

        client = OmniClient(config=_config())
        # async method on same client
        async_payload = await client.aget_cluster("cluster-a")
        assert "body" in async_payload

        await client.aclose()
