"""Tests for upstream control plane HTTP client."""

from __future__ import annotations

import pytest
import httpx

from radix_edge.upstream.client import UpstreamClient


@pytest.fixture
def upstream_client():
    return UpstreamClient(
        api_base="https://api.test.com",
        cluster_id="cluster-abc123",
        tenant_id="tenant-1",
        cluster_token="test-token-secret",
    )


class TestUpstreamClient:
    @pytest.mark.asyncio
    async def test_send_heartbeat(self, upstream_client, respx_mock):
        respx_mock.post("https://api.test.com/v1/clusters/cluster-abc123/heartbeat").respond(
            json={"status": "ok"}
        )

        result = await upstream_client.send_heartbeat("active", {"gpu_count": 1})
        assert result["status"] == "ok"
        await upstream_client.close()

    @pytest.mark.asyncio
    async def test_poll_jobs_empty(self, upstream_client, respx_mock):
        respx_mock.post("https://api.test.com/v1/clusters/cluster-abc123/jobs/poll").respond(
            json={"jobs": []}
        )

        jobs = await upstream_client.poll_jobs()
        assert jobs == []
        await upstream_client.close()

    @pytest.mark.asyncio
    async def test_poll_jobs_returns_job(self, upstream_client, respx_mock):
        mock_job = {"job_id": "job-abc", "job_kind": "training", "image": "img:1"}
        respx_mock.post("https://api.test.com/v1/clusters/cluster-abc123/jobs/poll").respond(
            json={"jobs": [mock_job]}
        )

        jobs = await upstream_client.poll_jobs()
        assert len(jobs) == 1
        assert jobs[0]["job_id"] == "job-abc"
        await upstream_client.close()

    @pytest.mark.asyncio
    async def test_complete_job(self, upstream_client, respx_mock):
        respx_mock.post(
            "https://api.test.com/v1/clusters/cluster-abc123/jobs/job-abc/complete"
        ).respond(json={"status": "ok"})

        result = await upstream_client.complete_job(
            "job-abc", "succeeded", metrics={"runtime_seconds": 42.0}
        )
        assert result["status"] == "ok"
        await upstream_client.close()

    @pytest.mark.asyncio
    async def test_auth_headers(self, upstream_client):
        client = await upstream_client._get_client()
        assert client.headers["X-Radix-Cluster-Token"] == "test-token-secret"
        assert client.headers["X-Radix-Tenant-Id"] == "tenant-1"
        await upstream_client.close()

    @pytest.mark.asyncio
    async def test_api_base_trailing_slash(self, respx_mock):
        uc = UpstreamClient(
            api_base="https://api.test.com/",
            cluster_id="c1",
            tenant_id="t1",
            cluster_token="tok",
        )
        respx_mock.post("https://api.test.com/v1/clusters/c1/heartbeat").respond(
            json={"status": "ok"}
        )
        result = await uc.send_heartbeat("active", {})
        assert result["status"] == "ok"
        await uc.close()

    @pytest.mark.asyncio
    async def test_heartbeat_error_propagates(self, upstream_client, respx_mock):
        respx_mock.post("https://api.test.com/v1/clusters/cluster-abc123/heartbeat").respond(
            status_code=500
        )

        with pytest.raises(httpx.HTTPStatusError):
            await upstream_client.send_heartbeat("active", {})
        await upstream_client.close()

    @pytest.mark.asyncio
    async def test_close_idempotent(self, upstream_client):
        await upstream_client.close()
        await upstream_client.close()  # Should not raise
