"""A stand-in chat model, so this course runs with no API key.

It is a real chat model as far as the rest of the code is concerned. It has
bind_tools, it returns a real AIMessage, and it asks for a tool when it thinks
one is needed. The only fake part is how it decides: a real model reads the
words and predicts, this one reads the words and follows four rules.
"""
from langchain_core.language_models import BaseChatModel
from langchain_core.messages import AIMessage
from langchain_core.outputs import ChatGeneration, ChatResult


def _first_id(text):
    """The first word with a digit in it, which is close enough to an id."""
    for word in text.replace("?", " ").replace(".", " ").replace(",", " ").split():
        if any(c.isdigit() for c in word):
            return word
    return ""


class PretendModel(BaseChatModel):
    tools: list = []

    @property
    def _llm_type(self):
        return "pretend"

    def bind_tools(self, tools, **kwargs):
        return PretendModel(tools=list(tools))

    def _generate(self, messages, stop=None, run_manager=None, **kwargs):
        return ChatResult(generations=[ChatGeneration(message=self._decide(messages))])

    def _decide(self, messages):
        last = messages[-1]
        if last.type == "tool":
            return AIMessage(f"Here is what I found. {last.content}")
        text = str(last.content)
        if text.startswith("Context:"):
            passage = text.split("Context:", 1)[1].split("Question:")[0].strip()
            return AIMessage(f"According to the documentation: {passage}")
        for t in self.tools:
            if any(w in text.lower() for w in t.name.split("_")):
                args = {}
                for name, spec in t.args.items():
                    value = _first_id(text)
                    args[name] = int(value) if spec.get("type") == "integer" else value
                return AIMessage("", tool_calls=[{"name": t.name, "args": args, "id": "call_1"}])
        found = _first_id(text)
        if found:
            return AIMessage(f"I can see the id {found}, but I have no way to look it up.")
        return AIMessage("I can help with that. What is the order id?")
