"""Tests for Goodmem / AsyncGoodmem constructor parameters.

Two mutually exclusive modes:
1. Simple: Goodmem(base_url, api_key, timeout=, verify=)
2. Full control: Goodmem(http_client=httpx.Client(...))
"""

from __future__ import annotations

from unittest.mock import MagicMock, patch

import httpx
import pytest

from goodmem.client import AsyncGoodmem, Goodmem


# ---------------------------------------------------------------------------
# Goodmem (sync) — Simple mode
# ---------------------------------------------------------------------------

class TestGoodmemInit:
    """Synchronous client constructor tests."""

    def test_default_construction(self):
        client = Goodmem(base_url="http://localhost:8080", api_key="gm_test")
        assert client._owns_http is True
        assert client._headers == {"x-api-key": "gm_test"}
        client.close()

    def test_verify_false(self):
        client = Goodmem(
            base_url="http://localhost:8080",
            api_key="gm_test",
            verify=False,
        )
        assert client._owns_http is True
        client.close()

    @patch("goodmem.client.httpx.Client")
    def test_verify_ca_path(self, mock_client_cls):
        mock_client_cls.return_value = MagicMock()
        client = Goodmem(
            base_url="http://localhost:8080",
            api_key="gm_test",
            verify="/path/to/ca.pem",
        )
        mock_client_cls.assert_called_once_with(
            base_url="http://localhost:8080",
            timeout=30.0,
            verify="/path/to/ca.pem",
        )
        assert client._owns_http is True

    def test_custom_timeout(self):
        client = Goodmem(
            base_url="http://localhost:8080",
            api_key="gm_test",
            timeout=120.0,
        )
        assert client._owns_http is True
        client.close()

    def test_missing_base_url_without_http_client(self):
        with pytest.raises(ValueError, match="base_url is required"):
            Goodmem(api_key="gm_test")

    def test_missing_api_key_without_http_client(self):
        with pytest.raises(ValueError, match="api_key is required"):
            Goodmem(base_url="http://localhost:8080")

    def test_context_manager_closes_owned_client(self):
        with Goodmem(base_url="http://localhost:8080", api_key="gm_test") as client:
            http = client._http
        assert http.is_closed


# ---------------------------------------------------------------------------
# Goodmem (sync) — http_client mode
# ---------------------------------------------------------------------------

class TestGoodmemHttpClient:
    """http_client mode: full control, mutually exclusive with simple params."""

    def test_http_client_accepted(self):
        custom = httpx.Client(base_url="http://custom:9090", headers={"x-api-key": "gm_ext"})
        client = Goodmem(http_client=custom)
        assert client._http is custom
        assert client._owns_http is False
        assert client._headers == {}  # SDK doesn't inject its own headers
        client.close()  # should NOT close the custom client
        assert not custom.is_closed
        custom.close()

    def test_http_client_with_base_url_raises(self):
        custom = httpx.Client(base_url="http://custom:9090")
        with pytest.raises(ValueError, match="base_url cannot be used together with http_client"):
            Goodmem(base_url="http://localhost:8080", http_client=custom)
        custom.close()

    def test_http_client_with_api_key_raises(self):
        custom = httpx.Client(base_url="http://custom:9090")
        with pytest.raises(ValueError, match="api_key cannot be used together with http_client"):
            Goodmem(api_key="gm_test", http_client=custom)
        custom.close()

    def test_http_client_with_timeout_raises(self):
        custom = httpx.Client(base_url="http://custom:9090")
        with pytest.raises(ValueError, match="timeout cannot be used together with http_client"):
            Goodmem(timeout=60.0, http_client=custom)
        custom.close()

    def test_http_client_with_verify_raises(self):
        custom = httpx.Client(base_url="http://custom:9090")
        with pytest.raises(ValueError, match="verify cannot be used together with http_client"):
            Goodmem(verify=False, http_client=custom)
        custom.close()

    def test_context_manager_does_not_close_external_client(self):
        custom = httpx.Client(base_url="http://custom:9090")
        with Goodmem(http_client=custom) as client:
            pass
        assert not custom.is_closed
        custom.close()


# ---------------------------------------------------------------------------
# AsyncGoodmem
# ---------------------------------------------------------------------------

class TestAsyncGoodmemInit:
    """Async client constructor tests (init is synchronous)."""

    def test_default_construction(self):
        client = AsyncGoodmem(base_url="http://localhost:8080", api_key="gm_test")
        assert client._owns_http is True
        assert client._headers == {"x-api-key": "gm_test"}

    def test_http_client_accepted(self):
        custom = httpx.AsyncClient(base_url="http://custom:9090", headers={"x-api-key": "gm_ext"})
        client = AsyncGoodmem(http_client=custom)
        assert client._http is custom
        assert client._owns_http is False
        assert client._headers == {}

    def test_http_client_with_base_url_raises(self):
        custom = httpx.AsyncClient(base_url="http://custom:9090")
        with pytest.raises(ValueError, match="base_url cannot be used together with http_client"):
            AsyncGoodmem(base_url="http://localhost:8080", http_client=custom)

    def test_http_client_with_api_key_raises(self):
        custom = httpx.AsyncClient(base_url="http://custom:9090")
        with pytest.raises(ValueError, match="api_key cannot be used together with http_client"):
            AsyncGoodmem(api_key="gm_test", http_client=custom)

    def test_missing_api_key_without_http_client(self):
        with pytest.raises(ValueError, match="api_key is required"):
            AsyncGoodmem(base_url="http://localhost:8080")

    def test_verify_false(self):
        client = AsyncGoodmem(
            base_url="http://localhost:8080",
            api_key="gm_test",
            verify=False,
        )
        assert client._owns_http is True
