//! Host-tool hooks — logging every lifecycle event around custom tools.
//!
//! Demonstrates:
//! - All five tool-related hook points: `PreTurn`, `PostTurn`,
//!   `PreToolCallDecide`, `PostToolCall`, `OnToolError`
//! - `Hooks` fluent builder for callback registration
//! - Custom tools that succeed and fail
//!
//! Note: `HookEntry` configuration is auto-generated by the `AgentBuilder`
//! from the `Hooks` instance — no manual `HookEntry` construction needed.

use agy_bridge::{
    config::CapabilitiesConfig,
    hooks::HookResult,
    prelude::*,
    tools::{ToolError, ToolOutput},
};

#[llm_tool]
/// Returns a greeting for the given name.
fn greet(
    /// The name to greet.
    name: &str,
) -> Result<String, ToolError> {
    Ok(format!("Hello, {name}!"))
}

#[llm_tool]
/// A tool that always fails. Useful for testing error handling.
fn broken_tool() -> Result<ToolOutput, ToolError> {
    Err(
        ToolError::new("RuntimeError: This tool is intentionally broken!")
            .with_meta("error_code", serde_json::json!("INTENTIONAL_FAILURE")),
    )
}

async fn run_prompt(agent: &Agent, prompt: &str) -> Result<(), Box<dyn std::error::Error>> {
    println!("\n{}", "=".repeat(60));
    println!("--- Sending: {prompt:?} ---");
    println!("{}", "=".repeat(60));
    let text = agent.chat(prompt).await?.text().await?;
    println!("\n--- Final response ---\n{text}\n");
    Ok(())
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    agy_bridge::load_dotenv();
    let bridge = AgyBridge::builder().build()?;

    let mut registry = ToolRegistry::new();
    registry.register(Greet);
    registry.register(BrokenTool);

    // Register all five hook points using convenience methods.
    let mut hooks = Hooks::new();

    hooks.on_pre_turn("log_pre_turn", |ctx| {
        println!("[Hook] Pre-turn — user prompt: {:?}", ctx.prompt);
    });

    hooks.on_post_turn("log_post_turn", |ctx| {
        println!(
            "[Hook] Post-turn — response len: {}",
            ctx.response_text.len()
        );
    });

    hooks.on_pre_tool_call_decide("log_pre_tool_call_decide", |ctx| {
        println!("[Hook] Pre-tool-call (decide) — tool: {}", ctx.tool_name);
        HookResult::allow()
    });

    hooks.on_post_tool_call("log_post_tool_call", |ctx| {
        println!("[Hook] Post-tool-call — result: {}", ctx.result);
    });

    hooks.on_tool_error("log_tool_error", |ctx| {
        println!("[Hook] Tool error — {}", ctx.error);
    });

    // No manual HookEntry construction needed — the AgentBuilder
    // auto-generates entries from the Hooks instance via hooks.entries().
    let config = AgentConfig::builder()
        .capabilities(CapabilitiesConfig::full())
        .policies(vec![PolicyRule::AllowAll])
        .build();

    let agent = bridge.agent(config).tools(registry).hooks(hooks).await?;

    run_prompt(&agent, "Please greet Alice using the greet tool.").await?;
    run_prompt(&agent, "Please call the broken_tool tool.").await?;
    run_prompt(&agent, "Ask me a multiple-choice trivia question.").await?;

    println!("\n--- All prompts complete ---");
    agent.shutdown().await?;
    Ok(())
}
