"""Tests for client.py — HTTP client with mocked responses."""

import json

import httpx
import pytest

from corpo.client import CorpoAPIError, CorpoClient


def test_get_realm(httpx_mock):
    """Test GET /api/v1/realm/{address}."""
    expected = {"address": "abc123", "realm": {"name": "Test"}}
    httpx_mock.add_response(
        url="http://test-api/api/v1/realm/abc123",
        json=expected,
    )
    client = CorpoClient("http://test-api")
    result = client.get_realm("abc123")
    assert result == expected


def test_list_realms(httpx_mock):
    expected = [{"address": "a"}, {"address": "b"}]
    httpx_mock.add_response(
        url="http://test-api/api/v1/realms",
        json=expected,
    )
    client = CorpoClient("http://test-api")
    result = client.list_realms()
    assert result == expected


def test_list_proposals(httpx_mock):
    expected = [{"name": "Prop1"}]
    httpx_mock.add_response(json=expected)
    client = CorpoClient("http://test-api")
    result = client.list_proposals("gov123")
    assert result == expected


def test_tx_create_realm(httpx_mock):
    expected = {"transaction": "base64data", "blockhash": "abc", "fee_payer": "xyz"}
    httpx_mock.add_response(json=expected)
    client = CorpoClient("http://test-api")
    result = client.tx_create_realm({"fee_payer": "xyz", "name": "Test"})
    assert result["transaction"] == "base64data"


def test_tx_api_error(httpx_mock):
    httpx_mock.add_response(
        status_code=400,
        json={"error": "bad request"},
        headers={"content-type": "application/json"},
    )
    client = CorpoClient("http://test-api")
    with pytest.raises(CorpoAPIError) as exc_info:
        client.tx_create_realm({"fee_payer": "bad"})
    assert exc_info.value.status_code == 400
    assert "bad request" in exc_info.value.message


@pytest.fixture
def httpx_mock(monkeypatch):
    """Simple httpx mock that intercepts Client requests."""
    mock = HttpxMock()
    original_init = httpx.Client.__init__

    def patched_init(self, *args, **kwargs):
        original_init(self, *args, **kwargs)
        mock._client = self

    monkeypatch.setattr(httpx.Client, "get", mock._mock_get)
    monkeypatch.setattr(httpx.Client, "post", mock._mock_post)
    return mock


class HttpxMock:
    def __init__(self):
        self._responses = []

    def add_response(self, url=None, json=None, status_code=200, headers=None):
        self._responses.append({
            "url": url,
            "json": json,
            "status_code": status_code,
            "headers": headers or {"content-type": "application/json"},
        })

    def _find_response(self, url):
        for resp in self._responses:
            if resp["url"] is None or str(url).startswith(resp["url"]):
                return resp
        # Return the first response if no URL match
        if self._responses:
            return self._responses[0]
        raise RuntimeError(f"No mock response for {url}")

    def _mock_get(self, path, **kwargs):
        base_url = ""
        if hasattr(self, "_base_url"):
            base_url = self._base_url
        resp_data = self._find_response(path)
        return httpx.Response(
            status_code=resp_data["status_code"],
            json=resp_data["json"],
            headers=resp_data["headers"],
            request=httpx.Request("GET", path),
        )

    def _mock_post(self, path, **kwargs):
        resp_data = self._find_response(path)
        return httpx.Response(
            status_code=resp_data["status_code"],
            json=resp_data["json"],
            headers=resp_data["headers"],
            request=httpx.Request("POST", path),
        )
