from __future__ import annotations

import asyncio
import runpy
import sys

import examples.async_basic as async_basic
import examples.filters as filters_example
import examples.sync_basic as sync_basic
import pytest

import kyrodb


class _SyncFakeClient:
    def __enter__(self) -> _SyncFakeClient:
        return self

    def __exit__(self, exc_type, exc, tb) -> None:  # type: ignore[no-untyped-def]
        return None

    def wait_for_ready(self, timeout_s: float = 5) -> None:
        _ = timeout_s

    def insert(self, **kwargs: object) -> None:
        _ = kwargs

    def search(self, **kwargs: object) -> object:
        _ = kwargs
        return type("_Result", (), {"total_found": 1})()


class _AsyncFakeClient:
    async def __aenter__(self) -> _AsyncFakeClient:
        return self

    async def __aexit__(self, exc_type, exc, tb) -> None:  # type: ignore[no-untyped-def]
        return None

    async def wait_for_ready(self, timeout_s: float = 5) -> None:
        _ = timeout_s

    async def insert(self, **kwargs: object) -> None:
        _ = kwargs

    async def search(self, **kwargs: object) -> object:
        _ = kwargs
        return type("_Result", (), {"total_found": 1})()


def test_sync_example_runs_without_live_server(monkeypatch: pytest.MonkeyPatch) -> None:
    monkeypatch.setattr(sync_basic, "KyroDBClient", lambda *args, **kwargs: _SyncFakeClient())
    sync_basic.main()


@pytest.mark.asyncio
async def test_async_example_runs_without_live_server(monkeypatch: pytest.MonkeyPatch) -> None:
    monkeypatch.setattr(
        async_basic,
        "AsyncKyroDBClient",
        lambda *args, **kwargs: _AsyncFakeClient(),
    )
    await async_basic.main()


def test_filters_example_runs() -> None:
    filters_example.main()


def test_async_example_entrypoint_calls_main(monkeypatch: pytest.MonkeyPatch) -> None:
    called = {"run_invoked": False}
    real_run = asyncio.run

    def fake_run(coro: object) -> object:
        called["run_invoked"] = True
        return real_run(coro)  # type: ignore[arg-type]

    monkeypatch.setattr(kyrodb, "AsyncKyroDBClient", lambda *args, **kwargs: _AsyncFakeClient())
    monkeypatch.setattr(asyncio, "run", fake_run)

    # Ensure run_module executes a fresh module, not an already-imported instance.
    sys.modules.pop("examples.async_basic", None)
    runpy.run_module("examples.async_basic", run_name="__main__")
    assert called["run_invoked"] is True
