"""Tests for htsget client."""

from __future__ import annotations

import pytest
from pytest_httpx import HTTPXMock

from ai4gh.specs.htsget.client import HtsgetClient
from ai4gh.specs.htsget.models import HtsgetClass, HtsgetFormat

READS_TICKET_RESPONSE = {
    "htsget": {
        "format": "BAM",
        "urls": [
            {
                "url": "https://example.com/header",
                "headers": {"Authorization": "Bearer x"},
                "data_class": "header",
            },
            {
                "url": "https://example.com/body",
                "data_class": "body",
            },
        ],
    }
}

VARIANTS_TICKET_RESPONSE = {
    "htsget": {
        "format": "VCF",
        "urls": [
            {"url": "https://example.com/variants/block1"},
        ],
    }
}


@pytest.fixture
def htsget_client() -> HtsgetClient:
    return HtsgetClient(base_url="https://htsget.example.com")


class TestHtsgetClient:
    def test_spec_attrs(self) -> None:
        client = HtsgetClient(base_url="https://example.com")
        assert client.spec_name == "htsget"
        assert client.spec_version == "1.3.0"

    async def test_get_reads(self, htsget_client: HtsgetClient, httpx_mock: HTTPXMock) -> None:
        httpx_mock.add_response(json=READS_TICKET_RESPONSE)
        ticket = await htsget_client.get_reads("sample1")
        assert ticket.htsget.format == HtsgetFormat.BAM
        assert len(ticket.htsget.urls) == 2

    async def test_get_reads_with_params(
        self, htsget_client: HtsgetClient, httpx_mock: HTTPXMock
    ) -> None:
        httpx_mock.add_response(json=READS_TICKET_RESPONSE)
        ticket = await htsget_client.get_reads(
            "sample1",
            format=HtsgetFormat.CRAM,
            data_class=HtsgetClass.header,
            reference_name="chr1",
            start=100,
            end=200,
            fields=["QNAME", "FLAG"],
            tags=["RG"],
            notags=["OQ"],
        )
        assert ticket.htsget.format == HtsgetFormat.BAM
        request = httpx_mock.get_requests()[0]
        url_str = str(request.url)
        assert "format=CRAM" in url_str
        assert "class=header" in url_str
        assert "referenceName=chr1" in url_str
        assert "start=100" in url_str
        assert "end=200" in url_str

    async def test_get_variants(self, htsget_client: HtsgetClient, httpx_mock: HTTPXMock) -> None:
        httpx_mock.add_response(json=VARIANTS_TICKET_RESPONSE)
        ticket = await htsget_client.get_variants("variant1")
        assert ticket.htsget.format == HtsgetFormat.VCF
        assert len(ticket.htsget.urls) == 1

    async def test_get_variants_with_region(
        self, htsget_client: HtsgetClient, httpx_mock: HTTPXMock
    ) -> None:
        httpx_mock.add_response(json=VARIANTS_TICKET_RESPONSE)
        ticket = await htsget_client.get_variants(
            "variant1",
            format=HtsgetFormat.BCF,
            reference_name="chr22",
            start=1000,
            end=5000,
        )
        assert ticket.htsget.format == HtsgetFormat.VCF
        request = httpx_mock.get_requests()[0]
        url_str = str(request.url)
        assert "format=BCF" in url_str
        assert "referenceName=chr22" in url_str

    def test_build_params_empty(self) -> None:
        params = HtsgetClient._build_params()
        assert params == {}

    def test_build_params_full(self) -> None:
        params = HtsgetClient._build_params(
            format=HtsgetFormat.BAM,
            data_class=HtsgetClass.body,
            reference_name="chr1",
            start=0,
            end=1000,
            fields=["QNAME"],
            tags=["RG", "BC"],
            notags=["OQ"],
        )
        assert params["format"] == "BAM"
        assert params["class"] == "body"
        assert params["referenceName"] == "chr1"
        assert params["start"] == 0
        assert params["end"] == 1000
        assert params["fields"] == "QNAME"
        assert params["tags"] == "RG,BC"
        assert params["notags"] == "OQ"
