from abc import ABC, abstractmethod

from harbor.models.metric import UsageInfo


class ContextLengthExceededError(Exception):
    """Raised when the LLM response indicates the context length was exceeded."""

    pass


class OutputLengthExceededError(Exception):
    """Raised when the LLM response was truncated due to max_tokens limit."""

    def __init__(self, message: str, truncated_response: str | None = None):
        super().__init__(message)
        self.truncated_response = truncated_response


class ParseError(Exception):
    """Raised when the LLM response cannot be parsed into the expected format."""

    pass


class BaseLLM(ABC):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

    @abstractmethod
    async def call(self, prompt: str, **kwargs) -> str:
        pass

    def get_last_logprobs(self) -> list[float] | None:
        """Get logprobs from the last LLM call.

        Returns:
            List of log probabilities for tokens in the last response, or None if not available.
        """
        return None

    def get_last_usage(self) -> UsageInfo | None:
        """Get token usage and cost from the last LLM call.

        Returns:
            UsageInfo with token counts and cost, or None if not available.
        """
        return None
