"""
05_nested_agents.py — Deeply nested synchronous agents (A calls B which calls C)

Tests the sync _parent_stack: each inner agent call happens INSIDE the outer
agent's function body, so the stack correctly records grandparent → parent → child.

Structure:
  orchestrator
    └─ analyst (called inside orchestrator)
         └─ fact_checker (called inside analyst)
              └─ citation_finder (called inside fact_checker)

WHAT THE DASHBOARD SHOULD SHOW:
  Live Graph:
    • Vertical or diagonal cascade: orchestrator → analyst → fact_checker → citation_finder
    • Each node one level deeper (the library detects nesting via _parent_stack)
    • 4 nodes, 3 edges — all green

  State View:
    • Step 1 — orchestrator: wide INPUT, OUTPUT = aggregated final dict
    • Step 2 — analyst:      INPUT = topic, OUTPUT = analysis text
    • Step 3 — fact_checker: INPUT = analysis, OUTPUT = {facts: [...], flags: [...]}
    • Step 4 — citation_finder: INPUT = facts, OUTPUT = citations list
    • (Steps appear in call ORDER, not return order — library captures start events)

  Time Travel:
    • Rewind to step 3 to see fact_checker output before citation_finder ran

  Token Dashboard:
    • Each agent has a bar — citation_finder likely smallest (factual lookup)
    • orchestrator bar = 0 tokens (it delegates, doesn't call LLM itself)

  Run Comparison:
    • orchestrator shows longest wall-clock (it waits for all children)
    • citation_finder shows shortest duration

  Failure History:
    • Empty
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from agentradar import radar, reset_run

load_dotenv()

llm = ChatOpenAI(
    api_key=os.getenv("DEEPSEEK_API_KEY"),
    base_url=os.getenv("DEEPSEEK_BASE_URL"),
    model=os.getenv("DEEPSEEK_MODEL", "deepseek-chat"),
    temperature=0.4,
)


@radar(tag="citation_finder", llm_input=["fact_checker"])
def citation_finder(facts: list) -> list:
    """Deepest agent: find citations for each fact."""
    facts_text = "\n".join(f"- {f}" for f in facts)
    message = llm.invoke(
        f"For each fact below, suggest one credible source or citation (author, year, or publication):\n{facts_text}"
    )
    return [line.strip() for line in message.content.split("\n") if line.strip()]


@radar(tag="fact_checker", llm_input=["analyst"])
def fact_checker(analysis: str) -> dict:
    """Middle agent: extract and verify facts from analysis."""
    message = llm.invoke(
        f"Extract 3 specific factual claims from this analysis. "
        f"Mark each as VERIFIED or QUESTIONABLE:\n{analysis}"
    )
    lines = [l.strip() for l in message.content.split("\n") if l.strip()]
    facts = [l for l in lines if "VERIFIED" in l or "QUESTIONABLE" in l]
    flags = [l for l in facts if "QUESTIONABLE" in l]

    # Nested call: fact_checker calls citation_finder internally
    citations = citation_finder(facts[:3] if facts else ["General claim about the topic"])

    return {
        "facts": facts,
        "flags": flags,
        "citations": citations,
        "verified_count": len(facts) - len(flags),
    }


@radar(tag="analyst", llm_input=["orchestrator"])
def analyst(topic: str) -> dict:
    """Middle agent: analyze the topic and verify facts."""
    message = llm.invoke(
        f"Analyze this topic in depth, covering causes, effects, and future implications:\n{topic}"
    )
    analysis_text = message.content

    # Nested call: analyst calls fact_checker internally
    fact_report = fact_checker(analysis_text)

    return {
        "analysis": analysis_text,
        "fact_report": fact_report,
        "word_count": len(analysis_text.split()),
    }


@radar(tag="orchestrator")
def orchestrator(topic: str) -> dict:
    """
    Top-level orchestrator: calls analyst, which calls fact_checker,
    which calls citation_finder — 4 levels of nesting.
    Doesn't call LLM itself (delegates to children).
    """
    print(f"[Orchestrator] Deep research on: {topic}")

    # Nested call: orchestrator calls analyst internally
    research = analyst(topic)

    return {
        "topic": topic,
        "analysis": research["analysis"][:200],
        "facts_verified": research["fact_report"]["verified_count"],
        "flags": research["fact_report"]["flags"],
        "citations": research["fact_report"]["citations"],
        "status": "complete",
    }


def main():
    reset_run()
    topic = "Climate change feedback loops and tipping points"

    print("=== Nested Agents (4 Levels Deep) ===\n")
    result = orchestrator(topic)

    print(f"\n[Results]")
    print(f"  Facts verified: {result['facts_verified']}")
    print(f"  Flags: {len(result['flags'])}")
    print(f"  Citations: {len(result['citations'])}")
    print(f"  Analysis preview: {result['analysis']}...")

    print("\n✓ Dashboard: 4-level cascade graph, orchestrator → analyst → fact_checker → citation_finder")


if __name__ == "__main__":
    main()
    input("\nPress Enter to view dashboard (http://localhost:7111) or Ctrl+C to exit...")
