"""
Base Model Adapter.

Abstract base class for model-specific context formatting.
"""

from abc import ABC, abstractmethod
from typing import Any, ClassVar

from ..types import BaseContext, ContextType


class ModelAdapter(ABC):
    """
    Abstract base adapter for model-specific context formatting.

    Each adapter knows how to format contexts for optimal
    understanding by a specific LLM family (Claude, OpenAI, etc.).
    """

    # Model name patterns this adapter handles
    MODEL_PATTERNS: ClassVar[list[str]] = []

    @classmethod
    def matches_model(cls, model: str) -> bool:
        """
        Check if this adapter handles the given model.

        Args:
            model: Model name to check

        Returns:
            True if this adapter handles the model
        """
        model_lower = model.lower()
        return any(pattern in model_lower for pattern in cls.MODEL_PATTERNS)

    @abstractmethod
    def format(
        self,
        contexts: list[BaseContext],
        **kwargs: Any,
    ) -> str:
        """
        Format contexts for the target model.

        Args:
            contexts: List of contexts to format
            **kwargs: Additional formatting options

        Returns:
            Formatted context string
        """
        ...

    @abstractmethod
    def format_type(
        self,
        contexts: list[BaseContext],
        context_type: ContextType,
        **kwargs: Any,
    ) -> str:
        """
        Format contexts of a specific type.

        Args:
            contexts: List of contexts of the same type
            context_type: The type of contexts
            **kwargs: Additional formatting options

        Returns:
            Formatted string for this context type
        """
        ...

    def get_type_order(self) -> list[ContextType]:
        """
        Get the preferred order of context types.

        Returns:
            List of context types in preferred order
        """
        return [
            ContextType.SYSTEM,
            ContextType.TASK,
            ContextType.KNOWLEDGE,
            ContextType.CONVERSATION,
            ContextType.TOOL,
        ]

    def group_by_type(
        self, contexts: list[BaseContext]
    ) -> dict[ContextType, list[BaseContext]]:
        """
        Group contexts by their type.

        Args:
            contexts: List of contexts to group

        Returns:
            Dictionary mapping context type to list of contexts
        """
        by_type: dict[ContextType, list[BaseContext]] = {}
        for context in contexts:
            ct = context.get_type()
            if ct not in by_type:
                by_type[ct] = []
            by_type[ct].append(context)
        return by_type

    def get_separator(self) -> str:
        """
        Get the separator between context sections.

        Returns:
            Separator string
        """
        return "\n\n"


class DefaultAdapter(ModelAdapter):
    """
    Default adapter for unknown models.

    Uses simple plain-text formatting with minimal structure.
    """

    MODEL_PATTERNS: ClassVar[list[str]] = []  # Fallback adapter

    @classmethod
    def matches_model(cls, model: str) -> bool:
        """Always returns True as fallback."""
        return True

    def format(
        self,
        contexts: list[BaseContext],
        **kwargs: Any,
    ) -> str:
        """Format contexts as plain text."""
        if not contexts:
            return ""

        by_type = self.group_by_type(contexts)
        parts: list[str] = []

        for ct in self.get_type_order():
            if ct in by_type:
                formatted = self.format_type(by_type[ct], ct, **kwargs)
                if formatted:
                    parts.append(formatted)

        return self.get_separator().join(parts)

    def format_type(
        self,
        contexts: list[BaseContext],
        context_type: ContextType,
        **kwargs: Any,
    ) -> str:
        """Format contexts of a type as plain text."""
        if not contexts:
            return ""

        content = "\n\n".join(c.content for c in contexts)

        if context_type == ContextType.SYSTEM:
            return content
        elif context_type == ContextType.TASK:
            return f"Task:\n{content}"
        elif context_type == ContextType.KNOWLEDGE:
            return f"Reference Information:\n{content}"
        elif context_type == ContextType.CONVERSATION:
            return f"Previous Conversation:\n{content}"
        elif context_type == ContextType.TOOL:
            return f"Tool Results:\n{content}"

        return content
