"""Agent configuration validator for digital employee.

This module provides the AgentConfigValidator class that handles
validation and normalization of agent configuration dictionaries.

Authors:
    Immanuel Rhesa (immanuel.rhesa@gdplabs.id)

References:
    NONE
"""

from typing import Any

from digital_employee_core.configuration.agent_configuration import (
    AgentConfigKeys,
    MemoryProvider,
    StepLimitConfig,
)


class AgentConfigValidator:
    """Validator for agent configuration dictionaries.

    This class provides validation and normalization for agent configuration
    dictionaries, including step limit config and memory provider settings.

    Attributes:
        _VALID_MEMORY_PROVIDERS: valid memory provider values for validation.
    """

    _VALID_MEMORY_PROVIDERS = frozenset(provider.value for provider in MemoryProvider)

    @staticmethod
    def ensure_valid_agent_config(agent_config: dict[str, Any]) -> dict[str, Any]:
        """Ensure agent config is valid.

        Args:
            agent_config (dict[str, Any]): Agent config to validate.

        Returns:
            dict[str, Any]: Validated agent config.
        """
        agent_config = agent_config.copy()
        if AgentConfigKeys.STEP_LIMIT_CONFIG in agent_config:
            step_limit_value = agent_config[AgentConfigKeys.STEP_LIMIT_CONFIG]
            if step_limit_value is not None:
                step_limit_dict = AgentConfigValidator._normalize_step_limit_config(step_limit_value)
                if step_limit_dict:
                    agent_config[AgentConfigKeys.STEP_LIMIT_CONFIG] = step_limit_dict
                else:
                    agent_config.pop(AgentConfigKeys.STEP_LIMIT_CONFIG, None)
            else:
                agent_config.pop(AgentConfigKeys.STEP_LIMIT_CONFIG, None)

        if AgentConfigKeys.MEMORY in agent_config:
            agent_config[AgentConfigKeys.MEMORY] = AgentConfigValidator._normalize_memory_provider(
                agent_config[AgentConfigKeys.MEMORY]
            )

        return agent_config

    @staticmethod
    def _normalize_step_limit_config(step_limit_config: Any) -> dict[str, Any]:
        """Normalize step limit configuration to a dictionary.

        Args:
            step_limit_config (Any): Step limit configuration, either a StepLimitConfig instance or dict.

        Returns:
            dict[str, Any]: Normalized step limit configuration as a dictionary.

        Raises:
            TypeError: If step_limit_config is not a StepLimitConfig instance or dict.
        """
        if isinstance(step_limit_config, dict):
            step_limit_object = StepLimitConfig.model_validate(step_limit_config)
        elif isinstance(step_limit_config, StepLimitConfig):
            step_limit_object = step_limit_config
        else:
            raise TypeError(
                f"step_limit_config must be a StepLimitConfig instance or dict, got {type(step_limit_config).__name__}"
            )

        return step_limit_object.to_dict()

    @staticmethod
    def _normalize_memory_provider(memory: Any) -> str | None:
        """Normalize memory provider to a string value.

        Args:
            memory (Any): Memory provider, either a MemoryProvider enum, string, or None.

        Returns:
            str | None: Normalized memory provider string, or None if not provided.

        Raises:
            TypeError: If memory is not a MemoryProvider, str, or None.
            ValueError: If memory provider string is not a supported provider.
        """
        if memory is None:
            memory_value = None
        elif isinstance(memory, MemoryProvider):
            memory_value = memory.value
        elif isinstance(memory, str):
            memory_value = memory.strip().lower()
        else:
            raise TypeError(f"memory must be a str or MemoryProvider, got {type(memory).__name__}")

        if memory_value is not None and memory_value not in AgentConfigValidator._VALID_MEMORY_PROVIDERS:
            raise ValueError(
                f"Unknown memory provider: {memory_value}. "
                f"Supported: {list(AgentConfigValidator._VALID_MEMORY_PROVIDERS)}"
            )

        return memory_value
