"""Tests for runtime components."""

import httpx
import pytest
import respx

from gnexus_gauth.config import GAuthConfig
from gnexus_gauth.exceptions import RuntimeApiException, TransportException
from gnexus_gauth.runtime import HttpRuntimeUserProvider


class TestHttpRuntimeUserProvider:
    def test_fetch_user_success(self) -> None:
        config = GAuthConfig(
            base_url="https://auth.example.test",
            client_id="billing",
            client_secret="secret",
            redirect_uri="https://billing.example.test/callback",
        )

        with respx.mock:
            route = respx.get("https://auth.example.test/oauth/userinfo").mock(
                return_value=httpx.Response(
                    200,
                    json={
                        "sub": "user_123",
                        "id": "user_123",
                        "email": "user@example.test",
                        "email_verified": True,
                        "system_role": "user",
                        "status": "active",
                        "profile": {"name": "Test User"},
                        "client": {
                            "client_id": "billing",
                            "roles": ["admin"],
                            "permissions": ["read", "write"],
                        },
                    },
                )
            )
            client = httpx.Client()
            provider = HttpRuntimeUserProvider(config, http_client=client)
            user = provider.fetch_user("access_token_123")

        assert user.user_id == "user_123"
        assert user.email == "user@example.test"
        assert user.email_verified is True
        assert user.system_role == "user"
        assert user.status == "active"
        assert user.profile == {"name": "Test User"}
        assert len(user.client_access_list) == 1
        assert user.client_access_list[0].client_id == "billing"
        assert user.client_access_list[0].role_ids == ["admin"]
        assert user.client_access_list[0].permission_ids == ["read", "write"]
        assert route.called
        request = route.calls.last.request
        assert request.headers["Authorization"] == "Bearer access_token_123"

    def test_fetch_user_error(self) -> None:
        config = GAuthConfig(
            base_url="https://auth.example.test",
            client_id="billing",
            client_secret="secret",
            redirect_uri="https://billing.example.test/callback",
        )

        with respx.mock:
            respx.get("https://auth.example.test/oauth/userinfo").mock(
                return_value=httpx.Response(401, json={"error": "Unauthorized"})
            )
            client = httpx.Client()
            provider = HttpRuntimeUserProvider(config, http_client=client)
            with pytest.raises(RuntimeApiException, match="error response"):
                provider.fetch_user("bad_token")

    def test_fetch_user_transport_error(self) -> None:
        config = GAuthConfig(
            base_url="https://auth.example.test",
            client_id="billing",
            client_secret="secret",
            redirect_uri="https://billing.example.test/callback",
        )

        with respx.mock:
            respx.get("https://auth.example.test/oauth/userinfo").mock(side_effect=httpx.ConnectError("Connection refused"))
            client = httpx.Client()
            provider = HttpRuntimeUserProvider(config, http_client=client)
            with pytest.raises(TransportException, match="runtime API failed"):
                provider.fetch_user("token")

    def test_fetch_user_malformed_json(self) -> None:
        config = GAuthConfig(
            base_url="https://auth.example.test",
            client_id="billing",
            client_secret="secret",
            redirect_uri="https://billing.example.test/callback",
        )

        with respx.mock:
            respx.get("https://auth.example.test/oauth/userinfo").mock(
                return_value=httpx.Response(200, text="not-json")
            )
            client = httpx.Client()
            provider = HttpRuntimeUserProvider(config, http_client=client)
            with pytest.raises(RuntimeApiException, match="malformed JSON"):
                provider.fetch_user("token")
