"""
Custom SendMessage Tool with Context Example

Demonstrates how to configure agent-to-agent communication via `communication_flows`
using a custom SendMessage tool (with an optional agency-level fallback).

Run with: python examples/custom_send_message.py
"""

import asyncio
import logging
import os
import sys

from pydantic import Field

# Path setup so the example can be run standalone
examples_root = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
sys.path.insert(0, os.path.join(examples_root, "src"))
sys.path.insert(0, examples_root)

from agency_swarm import Agency, Agent, ModelSettings, function_tool  # noqa: E402
from agency_swarm.tools.send_message import Handoff, SendMessage  # noqa: E402
from examples.utils import print_highlighted_send_message_args  # noqa: E402

# Setup logging
logging.basicConfig(level=logging.WARNING)
logging.getLogger("agency_swarm").setLevel(
    logging.DEBUG if os.getenv("DEBUG_LOGS", "False").lower() == "true" else logging.WARNING
)


# Custom SendMessage tool that adds key moments and decisions to the message
class SendMessageWithContext(SendMessage):
    """SendMessage with key moments and decisions tracking."""

    tool_name = "send_message_with_context"

    key_moments: str = Field(
        description=(
            "Document critical moments and decision points from the current conversation "
            "that the recipient agent needs to understand. Include context about what "
            "has been decided or prioritized that will guide the recipient's tool selection "
            "and task execution. For example: 'User decided to prioritize performance over cost', "
            "'Analysis focus shifted to Q4 optimization', etc."
        )
    )
    decisions: str = Field(
        description=(
            "Summarize the specific decisions made that will directly impact which tools "
            "or approaches the recipient agent should use. Be explicit about choices that "
            "narrow down the scope of work. For example: 'Prioritized performance analysis "
            "over cost reduction', 'Selected React over Vue for frontend', etc. This helps "
            "the recipient agent choose the most appropriate tools and approach."
        )
    )


# Define tools for testing
@function_tool
def analyze_costs() -> str:
    """Analyze cost reduction and budget optimization opportunities."""
    return "Cost analysis complete. $45,000 annual savings identified."


@function_tool
def analyze_performance() -> str:
    """Analyze system performance and optimization opportunities."""
    return "Performance analysis complete. 23% efficiency gain possible."


# Coordinator with custom SendMessage
coordinator = Agent(
    name="Coordinator",
    description="Project coordinator who delegates analysis tasks",
    instructions=(
        "Your name is Coordinator agent."
        "You coordinate analysis work. When delegating tasks, make clear decisions about "
        "the focus area and approach needed. "
        "CRITICAL: When you receive responses from specialists, you MUST include their "
        "complete, word-for-word response text in your final output. Do not summarize, "
        "paraphrase, or omit any details from their responses."
    ),
    model_settings=ModelSettings(temperature=0.0),
)

# Specialist with both analysis tools
specialist = Agent(
    name="Specialist",
    description="Specialist agent who performs performance or cost analysis",
    instructions=(
        "Your name is Specialist agent."
        "You perform analysis tasks using the appropriate tools. "
        "CRITICAL: After running any tool, you MUST copy the EXACT tool output "
        "into your response word-for-word, including any SECRET strings. "
        "Do not paraphrase, summarize, or rewrite the tool output. "
        "Include the complete raw result in your response."
    ),
    tools=[analyze_costs, analyze_performance],
    model_settings=ModelSettings(temperature=0.0),
)

agency = Agency(
    coordinator,
    specialist,
    communication_flows=[
        (coordinator > specialist, SendMessageWithContext),
        (specialist > coordinator, Handoff),
    ],
    shared_instructions="Use key decisions to guide analysis tool selection.",
)

# If you want a default communication tool for flows without explicit overrides, set
# send_message_tool_class on the Agency.
# agency = Agency(
#     coordinator,
#     specialist,
#     communication_flows=[coordinator > specialist, specialist > coordinator],
#     shared_instructions="Use key decisions to guide analysis tool selection.",
#     send_message_tool_class=SendMessageWithContext,
# )


# Helper function to visualize send message arguments
def print_send_message_args(agency, agent_name: str) -> None:
    print_highlighted_send_message_args(agency, agent_name=agent_name)


async def main():
    """Demonstrate key decisions being passed via custom SendMessage."""
    print("\nSendMessageWithContext Key Decisions Demo")

    # Turn 1: Initial discussion
    print("\n--- Turn 1: Send Message tool usage ---")
    initial_message = "Our Q4 operations need optimization. I want to focus on cost reduction."

    print(f"User: {initial_message}")
    response1 = await agency.get_response(message=initial_message)
    print(f"Coordinator: {response1.final_output}")
    print("\nSend Message arguments:")
    print_send_message_args(agency, "Coordinator")

    # Turn 2: Decision and delegation with random choice
    print("\n--- Turn 2: Handoff usage ---")
    delegate_message = "I've decided to prioritize performance analysis for Q4. Use the corresponding tool and transfer chat to the coordinator."

    print(f"Sending message to \033[32m{specialist.name}\033[0m: {delegate_message}")
    response2 = await agency.get_response(message=delegate_message, recipient_agent=specialist)
    print(f"\033[32m{response2.last_agent.name}\033[0m responded with: {response2.final_output}")

    print(
        "\n --- Key Takeaways: ---\n"
        "1. Coordinator agent's send message arguments include custom fields (SendMessageWithContext).\n"
        "2. The 2nd turn message is addressed to Specialist, but the final response is from Coordinator (handoff).\n"
    )


if __name__ == "__main__":
    asyncio.run(main())
