"""
Tests for DaisiClient.
"""

from unittest.mock import MagicMock, patch

import pytest

from daisi.client import DaisiClient
from daisi.config import DaisiConfig


class TestDaisiClientInitialization:
    """Test DaisiClient initialization."""

    def test_init_with_explicit_params(self) -> None:
        """Test initialization with explicit parameters."""
        client = DaisiClient(
            client_key="test-key",
            orc_address="test.daisi.net",
            orc_port=8443,
            use_ssl=True,
        )
        assert client.config.client_key == "test-key"
        assert client.config.orc_address == "test.daisi.net"
        assert client.config.orc_port == 8443
        assert client.config.use_ssl is True

    def test_init_creates_all_clients(self) -> None:
        """Test initialization creates all service clients."""
        client = DaisiClient(client_key="test-key")
        assert client.auth is not None
        assert client.session is not None
        assert client.inference is not None
        assert client.models is not None
        assert client.hosts is not None
        assert client.peers is not None
        assert client.settings is not None
        assert client.host_commands is not None
        assert client.app_commands is not None

    def test_init_with_env_variables(self) -> None:
        """Test initialization with environment variables."""
        with patch.dict(
            "os.environ",
            {
                "DAISI_CLIENT_KEY": "env-key",
                "DAISI_ORC_ADDRESS": "env.daisi.net",
                "DAISI_ORC_PORT": "9443",
            },
        ):
            client = DaisiClient()
            assert client.config.client_key == "env-key"
            assert client.config.orc_address == "env.daisi.net"
            assert client.config.orc_port == 9443


class TestDaisiClientClose:
    """Test DaisiClient close functionality."""

    def test_close_all_clients(self) -> None:
        """Test close method closes all service clients."""
        client = DaisiClient(client_key="test-key")

        # Mock close methods
        client.auth.close = MagicMock()
        client.session.close = MagicMock()
        client.inference.close = MagicMock()
        client.models.close = MagicMock()
        client.hosts.close = MagicMock()
        client.peers.close = MagicMock()
        client.settings.close = MagicMock()
        client.host_commands.close = MagicMock()
        client.app_commands.close = MagicMock()

        client.close()

        client.auth.close.assert_called_once()
        client.session.close.assert_called_once()
        client.inference.close.assert_called_once()
        client.models.close.assert_called_once()
        client.hosts.close.assert_called_once()
        client.peers.close.assert_called_once()
        client.settings.close.assert_called_once()
        client.host_commands.close.assert_called_once()
        client.app_commands.close.assert_called_once()


class TestDaisiClientContextManager:
    """Test DaisiClient context manager."""

    def test_context_manager_entry(self) -> None:
        """Test context manager __enter__ returns self."""
        client = DaisiClient(client_key="test-key")
        with client as ctx_client:
            assert ctx_client is client

    def test_context_manager_exit_closes(self) -> None:
        """Test context manager __exit__ calls close."""
        client = DaisiClient(client_key="test-key")
        client.close = MagicMock()

        with client:
            pass

        client.close.assert_called_once()

    def test_with_statement_usage(self) -> None:
        """Test using client with 'with' statement."""
        with DaisiClient(client_key="test-key") as client:
            assert isinstance(client, DaisiClient)
            assert client.config.client_key == "test-key"
