"""
Example demonstrating SQLite in-memory session with human-in-the-loop (HITL) tool approval.

This example shows how to use SQLite in-memory session memory combined with
human-in-the-loop tool approval. The session maintains conversation history while
requiring approval for specific tool calls.
"""

import asyncio

from agents import Agent, Runner, SQLiteSession, function_tool
from examples.auto_mode import confirm_with_fallback, input_with_fallback, is_auto_mode


async def _needs_approval(_ctx, _params, _call_id) -> bool:
    """Always require approval for weather tool."""
    return True


@function_tool(needs_approval=_needs_approval)
def get_weather(location: str) -> str:
    """Get weather for a location.

    Args:
        location: The location to get weather for

    Returns:
        Weather information as a string
    """
    # Simulated weather data
    weather_data = {
        "san francisco": "Foggy, 58°F",
        "oakland": "Sunny, 72°F",
        "new york": "Rainy, 65°F",
    }
    # Check if any city name is in the provided location string
    location_lower = location.lower()
    for city, weather in weather_data.items():
        if city in location_lower:
            return weather
    return f"Weather data not available for {location}"


async def prompt_yes_no(question: str) -> bool:
    """Prompt user for yes/no answer.

    Args:
        question: The question to ask

    Returns:
        True if user answered yes, False otherwise
    """
    return confirm_with_fallback(f"\n{question} (y/n): ", default=True)


async def main():
    # Create an agent with a tool that requires approval
    agent = Agent(
        name="HITL Assistant",
        instructions="You help users with information. Always use available tools when appropriate. Keep responses concise.",
        tools=[get_weather],
    )

    # Create an in-memory SQLite session instance that will persist across runs
    session = SQLiteSession(":memory:")
    session_id = session.session_id

    print("=== Memory Session + HITL Example ===")
    print(f"Session id: {session_id}")
    print("Enter a message to chat with the agent. Submit an empty line to exit.")
    print("The agent will ask for approval before using tools.\n")

    auto_mode = is_auto_mode()

    while True:
        # Get user input
        if auto_mode:
            user_message = input_with_fallback("You: ", "What's the weather in Oakland?")
        else:
            print("You: ", end="", flush=True)
            loop = asyncio.get_event_loop()
            user_message = await loop.run_in_executor(None, input)

        if not user_message.strip():
            break

        # Run the agent
        result = await Runner.run(agent, user_message, session=session)

        # Handle interruptions (tool approvals)
        while result.interruptions:
            # Get the run state
            state = result.to_state()

            for interruption in result.interruptions:
                tool_name = interruption.name or "Unknown tool"
                args = interruption.arguments or "(no arguments)"

                approved = await prompt_yes_no(
                    f"Agent {interruption.agent.name} wants to call '{tool_name}' with {args}. Approve?"
                )

                if approved:
                    state.approve(interruption)
                    print("Approved tool call.")
                else:
                    state.reject(interruption)
                    print("Rejected tool call.")

            # Resume the run with the updated state
            result = await Runner.run(agent, state, session=session)

        # Display the response
        reply = result.final_output or "[No final output produced]"
        print(f"Assistant: {reply}\n")
        if auto_mode:
            break


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