"""TRS v2.0.1 API client."""

from __future__ import annotations

from typing import Any

from ai4gh.core.client import GA4GHClient
from ai4gh.specs.trs.models import (
    DescriptorType,
    FileWrapper,
    Tool,
    ToolClass,
    ToolVersion,
)


class TRSClient(GA4GHClient):
    """Client for the GA4GH Tool Registry Service (TRS) v2.0.1.

    TRS provides a standard API for discovering and accessing
    tools and workflows in registries like Dockstore.
    """

    spec_name = "trs"
    spec_version = "2.0.1"
    base_path = "/ga4gh/trs/v2"

    async def get_tool_classes(self) -> list[ToolClass]:
        """Get available tool classes.

        Returns:
            List of tool classes (e.g., Workflow, Tool).
        """
        data = await self._request("GET", "/toolClasses")
        return [ToolClass.model_validate(item) for item in data]

    async def search_tools(
        self,
        *,
        name: str | None = None,
        description: str | None = None,
        organization: str | None = None,
        toolclass: str | None = None,
        descriptor_type: DescriptorType | None = None,
        registry: str | None = None,
        limit: int | None = None,
        offset: int | None = None,
    ) -> list[Tool]:
        """Search for tools.

        Args:
            name: Filter by tool name.
            description: Filter by description.
            organization: Filter by organization.
            toolclass: Filter by tool class.
            descriptor_type: Filter by descriptor type.
            registry: Filter by registry.
            limit: Maximum number of results.
            offset: Offset for pagination.

        Returns:
            List of matching tools.
        """
        params: dict[str, Any] = {}
        if name is not None:
            params["name"] = name
        if description is not None:
            params["description"] = description
        if organization is not None:
            params["organization"] = organization
        if toolclass is not None:
            params["toolclass"] = toolclass
        if descriptor_type is not None:
            params["descriptorType"] = descriptor_type.value
        if registry is not None:
            params["registry"] = registry
        if limit is not None:
            params["limit"] = limit
        if offset is not None:
            params["offset"] = offset

        data = await self._request("GET", "/tools", params=params or None)
        return [Tool.model_validate(item) for item in data]

    async def get_tool(self, tool_id: str) -> Tool:
        """Get a tool by ID.

        Args:
            tool_id: The tool identifier.

        Returns:
            The tool with all versions.
        """
        data = await self._request("GET", f"/tools/{tool_id}")
        return Tool.model_validate(data)

    async def get_tool_versions(self, tool_id: str) -> list[ToolVersion]:
        """Get versions of a tool.

        Args:
            tool_id: The tool identifier.

        Returns:
            List of tool versions.
        """
        data = await self._request("GET", f"/tools/{tool_id}/versions")
        return [ToolVersion.model_validate(item) for item in data]

    async def get_tool_version(self, tool_id: str, version_id: str) -> ToolVersion:
        """Get a specific version of a tool.

        Args:
            tool_id: The tool identifier.
            version_id: The version identifier.

        Returns:
            The tool version.
        """
        data = await self._request("GET", f"/tools/{tool_id}/versions/{version_id}")
        return ToolVersion.model_validate(data)

    async def get_descriptor(
        self,
        tool_id: str,
        version_id: str,
        descriptor_type: DescriptorType,
    ) -> FileWrapper:
        """Get the primary descriptor for a tool version.

        Args:
            tool_id: The tool identifier.
            version_id: The version identifier.
            descriptor_type: The descriptor type (CWL, WDL, etc.).

        Returns:
            The primary descriptor file.
        """
        data = await self._request(
            "GET",
            f"/tools/{tool_id}/versions/{version_id}/{descriptor_type.value}/descriptor",
        )
        return FileWrapper.model_validate(data)

    async def get_descriptor_files(
        self,
        tool_id: str,
        version_id: str,
        descriptor_type: DescriptorType,
    ) -> list[FileWrapper]:
        """Get all descriptor files for a tool version.

        Args:
            tool_id: The tool identifier.
            version_id: The version identifier.
            descriptor_type: The descriptor type.

        Returns:
            List of descriptor files.
        """
        data = await self._request(
            "GET",
            f"/tools/{tool_id}/versions/{version_id}/{descriptor_type.value}/files",
        )
        return [FileWrapper.model_validate(item) for item in data]
