"""Tests for bvd/sdk.py — httpx transport helpers."""
from __future__ import annotations

from unittest.mock import patch

import httpx
import pytest

from bvd.sdk import (
    AsyncBIBIVIDITransport,
    BIBIVIDITransport,
    _override_host,
    _rewrite_url,
    anthropic_http_client,
    async_anthropic_http_client,
    async_openai_http_client,
    openai_http_client,
)

# ── URL rewriting ─────────────────────────────────────────────────────────────

def test_rewrite_url_scheme_and_host():
    url = httpx.URL("https://api.anthropic.com/v1/messages")
    with patch("bvd.sdk.settings") as s:
        s.proxy_host = "127.0.0.1"
        s.proxy_port = 8080
        result = _rewrite_url(url)
    assert result.scheme == "http"
    assert result.host == "127.0.0.1"
    assert result.port == 8080


def test_rewrite_url_preserves_path_and_query():
    url = httpx.URL("https://api.openai.com/v1/chat/completions?foo=bar")
    with patch("bvd.sdk.settings") as s:
        s.proxy_host = "127.0.0.1"
        s.proxy_port = 8080
        result = _rewrite_url(url)
    assert result.path == "/v1/chat/completions"
    assert result.query == b"foo=bar"


# ── Host header override ──────────────────────────────────────────────────────

def test_override_host_replaces_existing():
    raw = [(b"host", b"old.host"), (b"content-type", b"application/json")]
    result = _override_host(raw, "api.anthropic.com")
    hosts = [v for k, v in result if k == b"host"]
    assert hosts == [b"api.anthropic.com"]
    # Other headers preserved
    assert (b"content-type", b"application/json") in result


def test_override_host_adds_when_absent():
    raw = [(b"content-type", b"application/json")]
    result = _override_host(raw, "api.anthropic.com")
    hosts = [v for k, v in result if k == b"host"]
    assert hosts == [b"api.anthropic.com"]


# ── Sync transport ────────────────────────────────────────────────────────────

def test_sync_transport_rewrites_request():
    """BIBIVIDITransport rewrites URL to proxy and preserves Host."""
    captured: list[httpx.Request] = []

    class _CapturingTransport(httpx.BaseTransport):
        def handle_request(self, request: httpx.Request) -> httpx.Response:
            captured.append(request)
            return httpx.Response(200, json={"ok": True})

    transport = BIBIVIDITransport()
    transport._inner = _CapturingTransport()  # type: ignore[assignment]

    with patch("bvd.sdk.settings") as s:
        s.proxy_host = "127.0.0.1"
        s.proxy_port = 8080
        req = httpx.Request(
            "POST",
            "https://api.anthropic.com/v1/messages",
            content=b'{"model":"claude"}',
        )
        transport.handle_request(req)

    assert len(captured) == 1
    sent = captured[0]
    assert sent.url.host == "127.0.0.1"
    assert sent.url.port == 8080
    assert sent.url.scheme == "http"
    assert sent.url.path == "/v1/messages"
    host_header = dict(sent.headers).get("host")
    assert host_header == "api.anthropic.com"


# ── Async transport ───────────────────────────────────────────────────────────

@pytest.mark.asyncio
async def test_async_transport_rewrites_request():
    """AsyncBIBIVIDITransport rewrites URL to proxy and preserves Host."""
    captured: list[httpx.Request] = []

    class _CapturingTransport(httpx.AsyncBaseTransport):
        async def handle_async_request(self, request: httpx.Request) -> httpx.Response:
            captured.append(request)
            return httpx.Response(200, json={"ok": True})

    transport = AsyncBIBIVIDITransport()
    transport._inner = _CapturingTransport()  # type: ignore[assignment]

    with patch("bvd.sdk.settings") as s:
        s.proxy_host = "127.0.0.1"
        s.proxy_port = 8080
        req = httpx.Request(
            "POST",
            "https://api.openai.com/v1/chat/completions",
            content=b'{"model":"gpt-4o"}',
        )
        await transport.handle_async_request(req)

    assert len(captured) == 1
    sent = captured[0]
    assert sent.url.host == "127.0.0.1"
    assert sent.url.port == 8080
    host_header = dict(sent.headers).get("host")
    assert host_header == "api.openai.com"


# ── Public helper factories ───────────────────────────────────────────────────

def test_anthropic_http_client_returns_httpx_client():
    c = anthropic_http_client()
    assert isinstance(c, httpx.Client)
    assert isinstance(c._transport, BIBIVIDITransport)  # type: ignore[attr-defined]
    c.close()


def test_async_anthropic_http_client_returns_async_client():
    c = async_anthropic_http_client()
    assert isinstance(c, httpx.AsyncClient)
    assert isinstance(c._transport, AsyncBIBIVIDITransport)  # type: ignore[attr-defined]


def test_openai_aliases():
    assert openai_http_client is anthropic_http_client
    assert async_openai_http_client is async_anthropic_http_client
