"""Unit tests for LMStudioManager lifecycle and health checker."""

from __future__ import annotations

import asyncio
import unittest
from unittest.mock import AsyncMock, MagicMock, patch

from app.modules.core.application.lmstudio_manager import LMStudioManager


class TestLMStudioManager(unittest.TestCase):
    @patch("httpx.AsyncClient.get")
    def test_is_server_running(self, mock_get: MagicMock) -> None:
        manager = LMStudioManager()

        # Success case
        mock_response = MagicMock()
        mock_response.status_code = 200
        mock_get.return_value = mock_response

        async def run_success():
            res = await manager.is_server_running()
            self.assertTrue(res)

        asyncio.run(run_success())

        # Failure case
        mock_get.side_effect = Exception("Connection refused")

        async def run_failure():
            res = await manager.is_server_running()
            self.assertFalse(res)

        asyncio.run(run_failure())

    @patch("shutil.which")
    @patch("asyncio.create_subprocess_exec")
    def test_start_server(
        self, mock_create_sub: MagicMock, mock_which: MagicMock
    ) -> None:
        manager = LMStudioManager()

        # CLI not installed
        mock_which.return_value = None

        async def run_no_cli():
            res = await manager.start_server()
            self.assertFalse(res)

        asyncio.run(run_no_cli())

        # CLI installed and starts successfully
        mock_which.return_value = "/usr/bin/lms"
        mock_process = AsyncMock()
        mock_process.communicate.return_value = (b"started", b"")
        mock_process.returncode = 0
        mock_create_sub.return_value = mock_process

        async def run_success_start():
            res = await manager.start_server()
            self.assertTrue(res)

        asyncio.run(run_success_start())
