"""Tests for WES client."""

from __future__ import annotations

import pytest
from pytest_httpx import HTTPXMock

from ai4gh.specs.wes.client import WESClient
from ai4gh.specs.wes.models import State

RUN_RESPONSE = {
    "run_id": "run-1",
    "state": "RUNNING",
    "request": {
        "workflow_url": "https://example.com/wf.cwl",
        "workflow_type": "CWL",
    },
    "run_log": {"name": "main", "exit_code": 0},
    "task_logs": [{"name": "task1", "exit_code": 0}],
    "outputs": {"result": "s3://bucket/out.bam"},
}


@pytest.fixture
def wes_client() -> WESClient:
    return WESClient(base_url="https://example.com")


class TestWESClient:
    def test_spec_attrs(self) -> None:
        client = WESClient(base_url="https://example.com")
        assert client.spec_name == "wes"
        assert client.spec_version == "1.1.0"
        assert client.base_path == "/ga4gh/wes/v1"

    def test_url(self) -> None:
        client = WESClient(base_url="https://example.com")
        assert client.url == "https://example.com/ga4gh/wes/v1"

    async def test_submit_run(self, wes_client: WESClient, httpx_mock: HTTPXMock) -> None:
        httpx_mock.add_response(
            url="https://example.com/ga4gh/wes/v1/runs",
            method="POST",
            json={"run_id": "run-new"},
        )
        result = await wes_client.submit_run(
            workflow_url="https://example.com/wf.cwl",
            workflow_params={"input": "data.bam"},
        )
        assert result.run_id == "run-new"
        request = httpx_mock.get_requests()[0]
        body = request.content.decode()
        assert "workflow_url" in body

    async def test_submit_run_with_tags(self, wes_client: WESClient, httpx_mock: HTTPXMock) -> None:
        httpx_mock.add_response(json={"run_id": "run-tagged"})
        result = await wes_client.submit_run(
            workflow_url="https://example.com/wf.cwl",
            tags={"project": "test"},
        )
        assert result.run_id == "run-tagged"

    async def test_get_run(self, wes_client: WESClient, httpx_mock: HTTPXMock) -> None:
        httpx_mock.add_response(
            url="https://example.com/ga4gh/wes/v1/runs/run-1",
            json=RUN_RESPONSE,
        )
        run = await wes_client.get_run("run-1")
        assert run.run_id == "run-1"
        assert run.state is State.RUNNING
        assert run.run_log.exit_code == 0

    async def test_get_run_status(self, wes_client: WESClient, httpx_mock: HTTPXMock) -> None:
        httpx_mock.add_response(
            url="https://example.com/ga4gh/wes/v1/runs/run-1/status",
            json={"run_id": "run-1", "state": "COMPLETE"},
        )
        status = await wes_client.get_run_status("run-1")
        assert status.run_id == "run-1"
        assert status.state is State.COMPLETE

    async def test_list_runs(self, wes_client: WESClient, httpx_mock: HTTPXMock) -> None:
        httpx_mock.add_response(
            url="https://example.com/ga4gh/wes/v1/runs",
            json={
                "runs": [
                    {"run_id": "r1", "state": "COMPLETE"},
                    {"run_id": "r2", "state": "RUNNING"},
                ],
                "next_page_token": "page2",
            },
        )
        resp = await wes_client.list_runs()
        assert len(resp.runs) == 2
        assert resp.next_page_token == "page2"

    async def test_list_runs_with_pagination(
        self, wes_client: WESClient, httpx_mock: HTTPXMock
    ) -> None:
        httpx_mock.add_response(json={"runs": []})
        await wes_client.list_runs(page_size=10, page_token="token-1")
        request = httpx_mock.get_requests()[0]
        assert "page_size=10" in str(request.url)
        assert "page_token=token-1" in str(request.url)

    async def test_cancel_run(self, wes_client: WESClient, httpx_mock: HTTPXMock) -> None:
        httpx_mock.add_response(
            url="https://example.com/ga4gh/wes/v1/runs/run-1/cancel",
            method="POST",
            json={"run_id": "run-1"},
        )
        result = await wes_client.cancel_run("run-1")
        assert result.run_id == "run-1"
