"""Tests for HTTP client (mocked)."""

import httpx
import pytest
import respx

from cnmaestro.client import CnMaestroClient, CnMaestroError


BASE = "https://example.test"


@pytest.fixture
def client(monkeypatch):
    monkeypatch.setenv("CNMAESTRO_BASE_URL", BASE)
    monkeypatch.setenv("CNMAESTRO_CLIENT_ID", "id")
    monkeypatch.setenv("CNMAESTRO_CLIENT_SECRET", "secret")
    c = CnMaestroClient()
    yield c
    c.close()


@respx.mock
def test_token_fetched_on_first_call(client):
    respx.post(f"{BASE}/api/v2/access/token").mock(
        return_value=httpx.Response(200, json={"access_token": "T1"})
    )
    respx.get(f"{BASE}/api/v2/devices").mock(
        return_value=httpx.Response(200, json={"data": [], "paging": {"total": 0}})
    )
    list(client.paginated("/api/v2/devices"))
    assert client._token == "T1"


@respx.mock
def test_401_triggers_refresh(client):
    token_route = respx.post(f"{BASE}/api/v2/access/token").mock(
        side_effect=[
            httpx.Response(200, json={"access_token": "T1"}),
            httpx.Response(200, json={"access_token": "T2"}),
        ]
    )
    respx.get(f"{BASE}/api/v2/devices").mock(
        side_effect=[
            httpx.Response(401),
            httpx.Response(200, json={"data": [], "paging": {"total": 0}}),
        ]
    )
    list(client.paginated("/api/v2/devices"))
    assert token_route.call_count == 2
    assert client._token == "T2"


@respx.mock
def test_paginated_walks_offsets(client):
    respx.post(f"{BASE}/api/v2/access/token").mock(
        return_value=httpx.Response(200, json={"access_token": "T"})
    )
    page1 = [{"mac": f"M{i}"} for i in range(100)]
    page2 = [{"mac": f"M{i}"} for i in range(100, 150)]
    respx.get(f"{BASE}/api/v2/devices", params={"limit": 100, "offset": 0}).mock(
        return_value=httpx.Response(200, json={"data": page1, "paging": {"total": 150}})
    )
    respx.get(f"{BASE}/api/v2/devices", params={"limit": 100, "offset": 100}).mock(
        return_value=httpx.Response(200, json={"data": page2, "paging": {"total": 150}})
    )
    items = list(client.paginated("/api/v2/devices"))
    assert len(items) == 150


@respx.mock
def test_delete_propagates_error(client):
    respx.post(f"{BASE}/api/v2/access/token").mock(
        return_value=httpx.Response(200, json={"access_token": "T"})
    )
    respx.delete(f"{BASE}/api/v2/devices/AA:BB").mock(
        return_value=httpx.Response(404, text="not found")
    )
    with pytest.raises(CnMaestroError):
        client.delete("/api/v2/devices/AA:BB")


def test_missing_credentials_raises(monkeypatch):
    monkeypatch.delenv("CNMAESTRO_CLIENT_ID", raising=False)
    monkeypatch.delenv("CNMAESTRO_CLIENT_SECRET", raising=False)
    with pytest.raises(CnMaestroError):
        CnMaestroClient()
