"""
AACPAutoGenAgent
A ConversableAgent subclass that receives and responds to AACP packets.

Key difference from LangChain and CrewAI:
AutoGen uses ConversableAgent as its base. Without AACP, agents
exchange full conversational messages in a GroupChat -- preamble,
clarifications, acknowledgements. AACP replaces all of that with
typed packets, eliminating the conversational overhead entirely.
"""

import os
import re
import json
import time
from typing import Optional

MODEL_COSTS = {
    "gpt-4o-mini":   0.15,
    "gpt-4o":        5.00,
    "gpt-4.1-mini":  0.40,
    "gpt-4.1":       2.00,
    "gpt-3.5-turbo": 0.50,
}

AACP_SYSTEM = """You understand AACP v1.4 pipe-delimited coordination packets.
Format: TASK|DOM|return:AGENT|p:PRIORITY|aacp:1.4|key:value...
Interpret packets directly. Respond with valid JSON only. No markdown fences."""


class AACPAutoGenAgent:
    """
    AutoGen ConversableAgent configured to receive AACP packets.
    Wraps AutoGen's agent with the standard AACPPacketBus interface.
    """

    def __init__(
        self,
        name:          str,
        domain:        str,
        system_prompt: str,
        model:         str = "gpt-4o-mini",
        api_key:       str = None,
    ):
        self.name      = name
        self.domain    = domain
        self.model     = model
        self.api_key   = api_key or os.environ.get("OPENAI_API_KEY")
        self._cpm      = MODEL_COSTS.get(model, 1.0)
        self._agent    = None
        self._system   = system_prompt + "\n\n" + AACP_SYSTEM
        self._setup()

    def _setup(self):
        """Initialise AutoGen ConversableAgent."""
        import autogen
        self._agent = autogen.ConversableAgent(
            name=self.name,
            system_message=self._system,
            llm_config={
                "config_list": [{
                    "model":   self.model,
                    "api_key": self.api_key,
                }],
                "temperature": 0,
                "max_tokens":  2000,
            },
            human_input_mode="NEVER",
            max_consecutive_auto_reply=1,
        )

    def receive(self, packet: str, data: dict = None) -> dict:
        """
        Receive an AACP packet and return a structured result.
        Uses AutoGen's ConversableAgent to process the packet.
        Compatible with AACPPacketBus interface.
        """
        import autogen

        parts = [f"Coordination packet:\n{packet}"]
        if data:
            parts.append(f"\nData:\n{json.dumps(data, indent=2)}")
        parts.append("\nRespond with valid JSON only. No markdown fences.")
        message = "\n".join(parts)

        # Create a temporary proxy to initiate the conversation
        proxy = autogen.ConversableAgent(
            name="PROXY",
            llm_config=False,
            human_input_mode="NEVER",
        )

        start = time.time()
        try:
            proxy.initiate_chat(
                self._agent,
                message=message,
                max_turns=1,
                silent=True,
            )
            latency_ms = (time.time() - start) * 1000

            # Extract last message from agent
            messages = self._agent.chat_messages.get(proxy, [])
            raw = ""
            for msg in reversed(messages):
                if msg.get("role") == "assistant" and msg.get("content"):
                    raw = msg["content"]
                    break

            # Strip markdown fences
            raw = re.sub(r"^```(?:json)?\s*", "", raw.strip())
            raw = re.sub(r"\s*```$", "", raw)
            result = json.loads(raw.strip())

            tokens_est = len(message.split()) * 2
            cost_usd   = tokens_est / 1_000_000 * self._cpm

            return {
                "result":     result,
                "tokens_in":  tokens_est,
                "tokens_out": len(raw.split()) * 2,
                "latency_ms": round(latency_ms, 0),
                "cost_usd":   round(cost_usd, 6),
                "error":      None,
            }

        except json.JSONDecodeError as e:
            return {
                "result": None, "tokens_in": 0, "tokens_out": 0,
                "latency_ms": round((time.time()-start)*1000, 0),
                "cost_usd": 0.0, "error": f"JSON parse error: {e}",
            }
        except Exception as e:
            return {
                "result": None, "tokens_in": 0, "tokens_out": 0,
                "latency_ms": round((time.time()-start)*1000, 0),
                "cost_usd": 0.0, "error": str(e),
            }


class AuditAgent:
    """Deterministic audit agent. No LLM. $0.00."""
    name   = "AUDIT-AGENT"
    domain = "LOG"

    def receive(self, packet: str, data: dict = None) -> dict:
        return {
            "result":     {"logged": True, "ts": time.time()},
            "tokens_in":  0, "tokens_out": 0,
            "latency_ms": 1, "cost_usd": 0.0, "error": None,
        }
