"""Tests for MCP tools."""

from __future__ import annotations

from ai4gh.mcp.tools import TOOLS, handle_tool_call, list_tools


class TestListTools:
    def test_returns_list(self) -> None:
        tools = list_tools()
        assert isinstance(tools, list)

    def test_has_tools(self) -> None:
        tools = list_tools()
        assert len(tools) == 13

    def test_tool_names(self) -> None:
        tools = list_tools()
        names = {t.name for t in tools}
        expected = {
            "drs_get_object",
            "beacon_query",
            "htsget_reads",
            "refget_sequence",
            "vrs_compute_id",
            "phenopacket_validate",
            "wes_submit_run",
            "tes_create_task",
            "trs_search_tools",
            "data_connect_search",
            "passport_decode",
            "duo_match",
            "pedigree_validate",
        }
        assert names == expected

    def test_all_tools_have_input_schema(self) -> None:
        for tool in TOOLS:
            assert tool.inputSchema
            assert tool.inputSchema["type"] == "object"
            assert "properties" in tool.inputSchema

    def test_all_tools_have_required_fields(self) -> None:
        for tool in TOOLS:
            assert "required" in tool.inputSchema

    def test_all_tools_have_description(self) -> None:
        for tool in TOOLS:
            assert tool.description


class TestHandleToolCall:
    async def test_unknown_tool(self) -> None:
        result = await handle_tool_call("nonexistent_tool", {})
        assert len(result) == 1
        assert "Unknown tool" in result[0].text

    async def test_phenopacket_validate_valid(self) -> None:
        result = await handle_tool_call(
            "phenopacket_validate",
            {"phenopacket": '{"id": "test-001", "subject": {"id": "patient-1"}}'},
        )
        assert len(result) == 1
        assert "Valid" in result[0].text or "test-001" in result[0].text

    async def test_phenopacket_validate_invalid_json(self) -> None:
        result = await handle_tool_call(
            "phenopacket_validate",
            {"phenopacket": "not-json"},
        )
        assert len(result) == 1
        assert "error" in result[0].text.lower() or "Error" in result[0].text

    async def test_vrs_compute_id(self) -> None:
        vrs_obj = '{"location": {"type": "SequenceLocation"}, "state": {"type": "LiteralSequenceExpression", "sequence": "T"}}'
        result = await handle_tool_call(
            "vrs_compute_id",
            {"type": "Allele", "definition": vrs_obj},
        )
        assert len(result) == 1
        assert "ga4gh:" in result[0].text

    async def test_passport_decode(self) -> None:
        import jwt

        token = jwt.encode(
            {
                "sub": "user-1",
                "iss": "https://issuer.example.com",
                "iat": 1700000000,
                "exp": 1800000000,
                "ga4gh_visa_v1": {
                    "type": "ControlledAccessGrants",
                    "value": "https://example.com/ds/1",
                    "source": "https://example.com",
                    "by": "dac",
                },
            },
            "secret",
            algorithm="HS256",
        )
        result = await handle_tool_call("passport_decode", {"token": token})
        assert len(result) == 1
        assert "user-1" in result[0].text

    async def test_pedigree_validate_valid(self) -> None:
        import json

        pedigree = json.dumps(
            {
                "individuals": [
                    {"id": "P1", "sex": "male", "affected_status": "affected"},
                    {"id": "P2", "sex": "female", "affected_status": "unaffected"},
                ],
                "relationships": [],
            }
        )
        result = await handle_tool_call(
            "pedigree_validate",
            {"pedigree": pedigree},
        )
        assert len(result) == 1
        assert "Valid" in result[0].text or "2 individuals" in result[0].text

    async def test_pedigree_validate_invalid_json(self) -> None:
        result = await handle_tool_call(
            "pedigree_validate",
            {"pedigree": "not-json"},
        )
        assert len(result) == 1
        assert "error" in result[0].text.lower() or "Error" in result[0].text

    async def test_duo_match(self) -> None:
        result = await handle_tool_call(
            "duo_match",
            {
                "conditions": [{"code": "DUO:0000042"}],  # GRU
                "purpose": {"codes": ["DUO:0000042"], "description": "General cancer research"},
            },
        )
        assert len(result) == 1
