#!/usr/bin/env python3

"""Utilities for file reading and parsing

![status](../../../badges/status-readers-utils.svg)
"""

from __future__ import annotations

from collections.abc import Sequence

from langchain_core.messages import BaseMessage
from langchain_core.messages.utils import convert_to_messages


class InvalidMessageFormatError(Exception):
    """Exception that is raised when a dictionary cannot be parsed into a valid
    [:simple-langchain: `BaseMessage`](https://reference.langchain.com/python/langchain-core/messages/base/BaseMessage),
    either because it is missing a required key or because the message type is not supported.
    """

    pass


def messages_from_dicts(dicts: dict | Sequence[dict]) -> list[BaseMessage]:
    """Convert a sequence of dictionaries to a list of `BaseMessage` objects.

    Args:
        dicts (dict | Sequence[dict]): A single or a sequence of dictionaries to be
            converted into `BaseMessage` objects.

            - If a single dictionary is provided, the method will look for a
                `"messages"` key containing a list of message dictionaries to
                convert.
            - If more than one dictionary or a single dictionary without a
                `"messages"` key is provided, the method assumes that the input
                corresponds to a sequence of dictionaries, each representing a
                single message to be converted.

    Returns:
        list[BaseMessage]: A list of BaseMessage objects created from the input
            dictionaries.

    Raises:
        InvalidMessageFormatError: If any of the input dictionaries cannot be
            parsed into a valid `BaseMessage` format, an error will be raised.

    Note:
        This method is a convenience wrapper around
        [:simple-langchain: `langchain_core.messages.utils.convert_to_messages`](https://github.com/langchain-ai/langchain/blob/master/libs/core/langchain_core/messages/utils.py#L735)
        and as such is subject to changes in the langchain-core library.
    """
    try:
        if isinstance(dicts, dict):
            if "messages" in dicts:
                # {"messages":[{"role":"...","content":"..."},...]}"
                return convert_to_messages(dicts["messages"])
            # {"role":"...","content":"..."}
            return convert_to_messages([dicts])
        # [{"role":"...","content":"..."},...]
        return convert_to_messages(dicts)
    except ValueError as e:  # missing key
        raise InvalidMessageFormatError(
            "One or more dictionaries are missing required keys for conversion to "
            "BaseMessage format."
        ) from e
    except NotImplementedError as e:  # pragma: no cover
        # raised by langchain on unsupported message type
        raise InvalidMessageFormatError(
            "One or more dictionaries contain an unsupported message type for "
            "conversion to BaseMessage format."
        ) from e
