"""Tests for Beacon v2 client."""

from __future__ import annotations

import pytest
from pytest_httpx import HTTPXMock

from ai4gh.specs.beacon.client import BeaconClient
from ai4gh.specs.beacon.models import Granularity

BEACON_INFO_RESPONSE = {
    "response": {
        "id": "org.example.beacon",
        "name": "Example Beacon",
        "api_version": "v2.0.0",
    }
}

BEACON_QUERY_RESPONSE = {
    "meta": {
        "beacon_id": "org.example.beacon",
        "api_version": "v2.0.0",
        "returned_granularity": "record",
    },
    "response_summary": {"exists": True, "numTotalResults": 5},
    "response": {"resultSets": []},
}


@pytest.fixture
def beacon_client() -> BeaconClient:
    return BeaconClient(base_url="https://beacon.example.com")


class TestBeaconClient:
    def test_spec_attrs(self) -> None:
        client = BeaconClient(base_url="https://beacon.example.com")
        assert client.spec_name == "beacon"
        assert client.spec_version == "2.0.0"

    async def test_get_info(self, beacon_client: BeaconClient, httpx_mock: HTTPXMock) -> None:
        httpx_mock.add_response(json=BEACON_INFO_RESPONSE)
        info = await beacon_client.get_info()
        assert info.id == "org.example.beacon"
        assert info.name == "Example Beacon"

    async def test_get_info_flat_response(
        self, beacon_client: BeaconClient, httpx_mock: HTTPXMock
    ) -> None:
        httpx_mock.add_response(
            json={
                "id": "flat-beacon",
                "name": "Flat Beacon",
            }
        )
        info = await beacon_client.get_info()
        assert info.id == "flat-beacon"

    async def test_get_configuration(
        self, beacon_client: BeaconClient, httpx_mock: HTTPXMock
    ) -> None:
        httpx_mock.add_response(json={"maturityAttributes": {"productionStatus": "DEV"}})
        config = await beacon_client.get_configuration()
        assert "maturityAttributes" in config

    async def test_get_map(self, beacon_client: BeaconClient, httpx_mock: HTTPXMock) -> None:
        httpx_mock.add_response(json={"endpointSets": {}})
        result = await beacon_client.get_map()
        assert "endpointSets" in result

    async def test_get_entry_types(
        self, beacon_client: BeaconClient, httpx_mock: HTTPXMock
    ) -> None:
        httpx_mock.add_response(json={"entryTypes": {}})
        result = await beacon_client.get_entry_types()
        assert "entryTypes" in result

    async def test_get_filtering_terms(
        self, beacon_client: BeaconClient, httpx_mock: HTTPXMock
    ) -> None:
        httpx_mock.add_response(json={"filteringTerms": []})
        result = await beacon_client.get_filtering_terms(skip=0, limit=10)
        assert "filteringTerms" in result

    async def test_query_post(self, beacon_client: BeaconClient, httpx_mock: HTTPXMock) -> None:
        httpx_mock.add_response(json=BEACON_QUERY_RESPONSE)
        response = await beacon_client.query("individuals")
        assert response.meta is not None
        assert response.meta.beacon_id == "org.example.beacon"

    async def test_query_with_filters(
        self, beacon_client: BeaconClient, httpx_mock: HTTPXMock
    ) -> None:
        httpx_mock.add_response(json=BEACON_QUERY_RESPONSE)
        response = await beacon_client.query(
            "individuals",
            filters=[{"id": "HP:0001250"}],
            granularity=Granularity.count,
        )
        assert response.response_summary is not None

    async def test_query_with_pagination(
        self, beacon_client: BeaconClient, httpx_mock: HTTPXMock
    ) -> None:
        httpx_mock.add_response(json=BEACON_QUERY_RESPONSE)
        response = await beacon_client.query("biosamples", skip=10, limit=20)
        assert response.meta is not None

    async def test_query_get(self, beacon_client: BeaconClient, httpx_mock: HTTPXMock) -> None:
        httpx_mock.add_response(json=BEACON_QUERY_RESPONSE)
        response = await beacon_client.query_get("g_variants", skip=0, limit=5)
        assert response.meta is not None
