"""Beacon v2 compliance test suite."""

from __future__ import annotations

import httpx

from ai4gh.compliance.runner import ComplianceSuite, TestResult, TestStatus, register_suite


@register_suite("beacon")
class BeaconComplianceSuite(ComplianceSuite):
    """Test GA4GH Beacon v2 API compliance."""

    spec_name = "beacon"
    spec_version = "2.0.0"

    async def test_info_endpoint(self) -> TestResult:
        """GET /info returns beacon information."""
        async with httpx.AsyncClient() as client:
            resp = await client.get(f"{self.base_url}/info")
        if resp.status_code != 200:
            return TestResult(
                name="test_info_endpoint",
                status=TestStatus.FAIL,
                message=f"Expected 200, got {resp.status_code}",
                spec=self.spec_name,
                endpoint="/info",
            )
        data = resp.json()
        if "response" not in data and "id" not in data:
            return TestResult(
                name="test_info_endpoint",
                status=TestStatus.FAIL,
                message="Response missing 'id' or 'response' field",
                spec=self.spec_name,
                endpoint="/info",
            )
        return TestResult(
            name="test_info_endpoint",
            status=TestStatus.PASS,
            spec=self.spec_name,
            endpoint="/info",
        )

    async def test_service_info(self) -> TestResult:
        """GET /service-info returns GA4GH service info."""
        async with httpx.AsyncClient() as client:
            resp = await client.get(f"{self.base_url}/service-info")
        if resp.status_code != 200:
            return TestResult(
                name="test_service_info",
                status=TestStatus.FAIL,
                message=f"Expected 200, got {resp.status_code}",
                spec=self.spec_name,
                endpoint="/service-info",
            )
        data = resp.json()
        if "type" not in data:
            return TestResult(
                name="test_service_info",
                status=TestStatus.FAIL,
                message="Missing 'type' in service-info response",
                spec=self.spec_name,
                endpoint="/service-info",
            )
        return TestResult(
            name="test_service_info",
            status=TestStatus.PASS,
            spec=self.spec_name,
            endpoint="/service-info",
        )

    async def test_map_endpoint(self) -> TestResult:
        """GET /map returns beacon map (entry types)."""
        async with httpx.AsyncClient() as client:
            resp = await client.get(f"{self.base_url}/map")
        if resp.status_code != 200:
            return TestResult(
                name="test_map_endpoint",
                status=TestStatus.FAIL,
                message=f"Expected 200, got {resp.status_code}",
                spec=self.spec_name,
                endpoint="/map",
            )
        return TestResult(
            name="test_map_endpoint",
            status=TestStatus.PASS,
            spec=self.spec_name,
            endpoint="/map",
        )

    async def test_configuration_endpoint(self) -> TestResult:
        """GET /configuration returns beacon configuration."""
        async with httpx.AsyncClient() as client:
            resp = await client.get(f"{self.base_url}/configuration")
        if resp.status_code != 200:
            return TestResult(
                name="test_configuration_endpoint",
                status=TestStatus.FAIL,
                message=f"Expected 200, got {resp.status_code}",
                spec=self.spec_name,
                endpoint="/configuration",
            )
        return TestResult(
            name="test_configuration_endpoint",
            status=TestStatus.PASS,
            spec=self.spec_name,
            endpoint="/configuration",
        )

    async def test_filtering_terms(self) -> TestResult:
        """GET /filtering_terms returns available filters."""
        async with httpx.AsyncClient() as client:
            resp = await client.get(f"{self.base_url}/filtering_terms")
        if resp.status_code != 200:
            return TestResult(
                name="test_filtering_terms",
                status=TestStatus.FAIL,
                message=f"Expected 200, got {resp.status_code}",
                spec=self.spec_name,
                endpoint="/filtering_terms",
            )
        return TestResult(
            name="test_filtering_terms",
            status=TestStatus.PASS,
            spec=self.spec_name,
            endpoint="/filtering_terms",
        )

    async def test_individuals_endpoint(self) -> TestResult:
        """POST /individuals returns individuals query results."""
        async with httpx.AsyncClient() as client:
            resp = await client.post(
                f"{self.base_url}/individuals",
                json={"query": {"requestParameters": {}}},
            )
        if resp.status_code not in (200, 401, 403):
            return TestResult(
                name="test_individuals_endpoint",
                status=TestStatus.FAIL,
                message=f"Expected 200/401/403, got {resp.status_code}",
                spec=self.spec_name,
                endpoint="/individuals",
            )
        return TestResult(
            name="test_individuals_endpoint",
            status=TestStatus.PASS,
            spec=self.spec_name,
            endpoint="/individuals",
        )
