from __future__ import annotations

import types

import pytest

from app.livekit.compat import patch_inference_executor_is_alive


def test_patch_inference_executor_is_alive_handles_closed_process(monkeypatch) -> None:
    fake_module = types.SimpleNamespace()

    class FakeInferenceProcExecutor:
        def is_alive(self) -> bool:
            raise ValueError("process object is closed")

    fake_module.InferenceProcExecutor = FakeInferenceProcExecutor

    monkeypatch.setattr(
        "app.livekit.compat.import_module",
        lambda name: fake_module,
    )

    patched = patch_inference_executor_is_alive()

    assert patched is True
    assert FakeInferenceProcExecutor().is_alive() is False


def test_patch_inference_executor_is_alive_preserves_other_value_errors(monkeypatch) -> None:
    fake_module = types.SimpleNamespace()

    class FakeInferenceProcExecutor:
        def is_alive(self) -> bool:
            raise ValueError("unexpected failure")

    fake_module.InferenceProcExecutor = FakeInferenceProcExecutor

    monkeypatch.setattr(
        "app.livekit.compat.import_module",
        lambda name: fake_module,
    )

    patch_inference_executor_is_alive()

    with pytest.raises(ValueError, match="unexpected failure"):
        FakeInferenceProcExecutor().is_alive()


def test_patch_inference_executor_is_alive_is_idempotent(monkeypatch) -> None:
    fake_module = types.SimpleNamespace()

    class FakeInferenceProcExecutor:
        calls = 0

        def is_alive(self) -> bool:
            type(self).calls += 1
            raise ValueError("process object is closed")

    fake_module.InferenceProcExecutor = FakeInferenceProcExecutor

    monkeypatch.setattr(
        "app.livekit.compat.import_module",
        lambda name: fake_module,
    )

    first = patch_inference_executor_is_alive()
    second = patch_inference_executor_is_alive()

    assert first is True
    assert second is False
    assert FakeInferenceProcExecutor().is_alive() is False
    assert FakeInferenceProcExecutor.calls == 1
