"""
Integration mapper for converting API responses to domain models.

This module provides the IntegrationMapper class for mapping raw API response
dictionaries to structured ToolPlugin and ToolParameter objects.
"""

from typing import List

from pygeai.lab.models import ToolPlugin, ToolPluginList, ToolParameter


class IntegrationMapper:
    """
    Mapper class for converting API responses to Integration models.

    This class provides methods to map raw API response dictionaries to structured
    ToolPlugin and ToolParameter objects. It handles both v3 and v4 response formats.
    """

    @classmethod
    def map_to_integration(cls, data: dict) -> ToolPlugin:
        """
        Maps a dictionary to a ToolPlugin object using Pydantic model validation.

        This method handles integration data from both 'plugin' and 'toolPlugin' keys,
        as well as direct integration objects (v3 GET response returns direct object).

        :param data: dict - The raw data from API response.
            Expected fields include id, name, and potentially other integration metadata.
            Can be wrapped in 'plugin', 'toolPlugin', or be the object itself.
        :return: ToolPlugin - A ToolPlugin object representing the integration configuration.

        Example:
            >>> mapper = IntegrationMapper()
            >>> integration_data = {"plugin": {"id": "123", "name": "My Integration"}}
            >>> integration = mapper.map_to_integration(integration_data)
        """
        # Handle different response formats
        # v3 GET returns direct object, v4 or other endpoints may wrap it
        if "plugin" in data:
            plugin_data = data["plugin"]
        elif "toolPlugin" in data:
            plugin_data = data["toolPlugin"]
        else:
            # Direct object (v3 GET response format)
            plugin_data = data
        
        return ToolPlugin.model_validate(plugin_data)

    @classmethod
    def map_to_integration_list(cls, data: dict) -> ToolPluginList:
        """
        Maps an API response dictionary to a ToolPluginList object.

        This method extracts integrations from the given data, converts them into a list of
        ToolPlugin objects, and returns a ToolPluginList containing the list. It handles both
        'toolPlugins' (v3) and 'plugins' (v4) response keys.

        :param data: dict - The dictionary containing integration response data.
            Expected to have a 'toolPlugins' or 'plugins' key, or be a list directly.
        :return: ToolPluginList - A structured response containing a list of integrations.

        Example:
            >>> mapper = IntegrationMapper()
            >>> response_data = {"toolPlugins": [{"id": "1", "name": "Int1"}, {"id": "2", "name": "Int2"}]}
            >>> integration_list = mapper.map_to_integration_list(response_data)
            >>> len(integration_list)
            2
        """
        plugin_list = []

        # Handle different response formats: v3 uses 'toolPlugins', v4 uses 'plugins'
        if isinstance(data, list):
            plugins = data
        else:
            plugins = data.get("toolPlugins") or data.get("plugins") or []

        if plugins and any(plugins):
            for plugin_data in plugins:
                plugin = cls.map_to_integration(plugin_data)
                plugin_list.append(plugin)

        return ToolPluginList(plugins=plugin_list)

    @classmethod
    def map_to_config(cls, data: dict) -> List[ToolParameter]:
        """
        Maps an API config response dictionary to a list of ToolParameter objects.

        This method handles the integration configuration response which contains parameters
        that can be inherited by tools belonging to the integration.

        :param data: dict - The dictionary containing config response data.
            Expected to have a 'parameters' key or be a list directly.
        :return: List[ToolParameter] - A list of ToolParameter objects with inheritance metadata.

        Example input:
            {
                "parameters": [
                    {
                        "key": "clientId",
                        "dataType": "String",
                        "isRequired": True,
                        "type": "config",
                        "value": "mySecret",
                        "fromSecret": True
                    }
                ]
            }

        Example:
            >>> mapper = IntegrationMapper()
            >>> config_data = {"parameters": [{"key": "api_key", "type": "config", "value": "secret"}]}
            >>> parameters = mapper.map_to_config(config_data)
            >>> len(parameters)
            1
        """
        params_data = data if isinstance(data, list) else data.get("parameters", [])
        return cls._map_parameters(params_data)

    @classmethod
    def _map_parameters(cls, params_data: List[dict]) -> List[ToolParameter]:
        """
        Maps a list of parameter dictionaries to a list of ToolParameter objects.

        This method uses Pydantic's model_validate to handle all fields including
        the inheritance fields (isInherited, valueFrom) and other parameter metadata.

        :param params_data: List[dict] - List of raw parameter data from API response.
        :return: List[ToolParameter] - List of mapped ToolParameter objects.

        Example:
            >>> mapper = IntegrationMapper()
            >>> params = [{"key": "param1", "type": "config", "value": "val1"}]
            >>> mapped = mapper._map_parameters(params)
        """
        return [
            ToolParameter.model_validate(param)
            for param in params_data
        ]
