import asyncio
import json
import logging

from spade.behaviour import CyclicBehaviour
from spade.message import Message

from control_backend.core.config import settings


class BeliefFromText(CyclicBehaviour):
    logger = logging.getLogger("Belief From Text")

    # TODO: LLM prompt nog hardcoded
    llm_instruction_prompt = """
    You are an information extraction assistent for a BDI agent. Your task is to extract values \
    from a user's text to bind a list of ungrounded beliefs. Rules:
    You will receive a JSON object with "beliefs" (a list of ungrounded AgentSpeak beliefs) \
    and "text" (user's transcript).
    Analyze the text to find values that sematically match the variables (X,Y,Z) in the beliefs.
    A single piece of text might contain multiple instances that match a belief.
    Respond ONLY with a single JSON object.
    The JSON object's keys should be the belief functors (e.g., "weather").
    The value for each key must be a list of lists.
    Each inner list must contain the extracted arguments (as strings) for one instance \
    of that belief.
    CRITICAL: If no information in the text matches a belief, DO NOT include that key \
    in your response.
    """

    # on_start agent receives message containing the beliefs to look out for and
    # sets up the LLM with instruction prompt
    # async def on_start(self):
    #    msg = await self.receive(timeout=0.1)
    #    self.beliefs = dict uit message
    #    send instruction prompt to LLM

    beliefs: dict[str, list[str]]
    beliefs = {"mood": ["X"], "car": ["Y"]}

    async def run(self):
        msg = await self.receive(timeout=0.1)
        if msg:
            sender = msg.sender.node
            match sender:
                case settings.agent_settings.transcription_agent_name:
                    self.logger.info("Received text from transcriber.")
                    await self._process_transcription_demo(msg.body)
                case _:
                    self.logger.info("Received message from other agent.")
                    pass
        await asyncio.sleep(1)

    async def _process_transcription(self, text: str):
        text_prompt = f"Text: {text}"

        beliefs_prompt = "These are the beliefs to be bound:\n"
        for belief, values in self.beliefs.items():
            beliefs_prompt += f"{belief}({', '.join(values)})\n"

        prompt = text_prompt + beliefs_prompt
        self.logger.info(prompt)
        # prompt_msg = Message(to="LLMAgent@whatever")
        # response = self.send(prompt_msg)

        # Mock response; response is beliefs in JSON format, it parses do dict[str,list[list[str]]]
        response = '{"mood": [["happy"]]}'
        # Verify by trying to parse
        try:
            json.loads(response)
            belief_message = Message(
                to=settings.agent_settings.bdi_core_agent_name + "@" + settings.agent_settings.host,
                body=response,
            )
            belief_message.thread = "beliefs"

            await self.send(belief_message)
            self.logger.info("Sent beliefs to BDI.")
        except json.JSONDecodeError:
            # Parsing failed, so the response is in the wrong format, log warning
            self.logger.warning("Received LLM response in incorrect format.")

    async def _process_transcription_demo(self, txt: str):
        """
        Demo version to process the transcription input to beliefs. For the demo only the belief
        'user_said' is relevant, so this function simply makes a dict with key: "user_said",
        value: txt and passes this to the Belief Collector agent.
        """
        belief = {"beliefs": {"user_said": [txt]}, "type": "belief_extraction_text"}
        payload = json.dumps(belief)
        belief_msg = Message(
            to=settings.agent_settings.belief_collector_agent_name
            + "@"
            + settings.agent_settings.host,
            body=payload,
        )
        belief_msg.thread = "beliefs"

        await self.send(belief_msg)
        self.logger.info("Sent beliefs to Belief Collector.")
