"""Tools.

This module provides search and reflection tools for the research agent,
using Tavily for URL discovery and fetching full webpage content.
"""

import asyncio
from typing import Literal

import httpx
from dotenv import load_dotenv
from langchain_core.tools import InjectedToolArg, tool
from markdownify import markdownify
from tavily import TavilyClient
from typing_extensions import Annotated

load_dotenv(override=True)

tavily_client = TavilyClient()


async def fetch_webpage_content(url: str, timeout: float = 10.0) -> str:
    """Fetch and convert webpage content to markdown.

    Args:
        url: URL to fetch
        timeout: Request timeout in seconds

    Returns:
        Webpage content as markdown
    """
    headers = {
        "User-Agent": (
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
            "AppleWebKit/537.36 (KHTML, like Gecko) "
            "Chrome/91.0.4472.124 Safari/537.36"
        )
    }

    try:
        async with httpx.AsyncClient() as client:
            response = await client.get(url, headers=headers, timeout=timeout)
            response.raise_for_status()
            return markdownify(response.text)
    except Exception as e:
        return f"Error fetching content from {url}: {str(e)}"


@tool(parse_docstring=True)
async def tavily_search(
    query: str,
    max_results: Annotated[int, InjectedToolArg] = 3,
    topic: Annotated[
        Literal["general", "news", "finance"], InjectedToolArg
    ] = "general",
) -> str:
    """Search the web for information on a given query.

    Uses Tavily to discover relevant URLs, then fetches and returns
    full webpage content as markdown for comprehensive research.

    Args:
        query: Search query to execute

    Returns:
        Formatted search results with full webpage content in markdown
    """

    def _sync_search() -> dict:
        return tavily_client.search(
            query,
            max_results=max_results,
            topic=topic,
        )

    try:
        # Run Tavily search asynchronously
        search_results = await asyncio.to_thread(_sync_search)

        # Fetch full content for each URL concurrently
        results = search_results.get("results", [])
        if not results:
            return f"No results found for '{query}'"

        # Fetch all webpages concurrently
        fetch_tasks = [fetch_webpage_content(r["url"]) for r in results]
        contents = await asyncio.gather(*fetch_tasks)

        # Format results
        result_texts = []
        for result, content in zip(results, contents):
            result_text = f"""## {result["title"]}
**URL:** {result["url"]}

{content}

---
"""
            result_texts.append(result_text)

        return f"""Found {len(result_texts)} result(s) for '{query}':

{"".join(result_texts)}"""

    except Exception as e:
        return f"Search failed: {str(e)}"


@tool(parse_docstring=True)
def think_tool(reflection: str) -> str:
    """Tool for strategic reflection on research progress and decision-making.

    Use this tool after each search to analyze results and plan next steps systematically.
    This creates a deliberate pause in the research workflow for quality decision-making.

    When to use:
    - After receiving search results: What key information did I find?
    - Before deciding next steps: Do I have enough to answer comprehensively?
    - When assessing research gaps: What specific information am I still missing?
    - Before concluding research: Can I provide a complete answer now?

    Reflection should address:
    1. Analysis of current findings - What concrete information have I gathered?
    2. Gap assessment - What crucial information is still missing?
    3. Quality evaluation - Do I have sufficient evidence/examples for a good answer?
    4. Strategic decision - Should I continue searching or provide my answer?
    5. Skill leverage - Is there a relevant local skill to load that can accelerate this work?

    Args:
        reflection: Your detailed reflection on research progress, findings, gaps, and next steps

    Returns:
        Confirmation that reflection was recorded for decision-making
    """
    return f"Reflection recorded: {reflection}"
