"""Web tool for searching the internet and fetching URL content."""

from typing import Optional

from emdash.agent.tools.base import BaseTool, ToolResult, ToolCategory
from emdash.utils.logger import log


class WebTool(BaseTool):
    """Search the web or fetch content from a URL.

    This tool provides two modes:
    - search: Search the internet using DuckDuckGo
    - fetch: Retrieve and parse content from a specific URL

    Example:
        # Search the web
        result = tool.execute(mode="search", query="python async patterns")

        # Fetch URL content
        result = tool.execute(mode="fetch", url="https://docs.python.org/3/")
    """

    name = "web"
    description = """Search the web or fetch content from a URL.

Modes:
- search: Search the internet for information. Returns titles, URLs, and snippets.
- fetch: Retrieve content from a specific URL. Returns content as markdown.

Use 'search' to find relevant pages, then 'fetch' to get full content."""

    category = ToolCategory.SEARCH

    def execute(
        self,
        mode: str,
        query: Optional[str] = None,
        url: Optional[str] = None,
        max_results: int = 5,
    ) -> ToolResult:
        """Execute the web tool.

        Args:
            mode: Operation mode - 'search' or 'fetch'
            query: Search query (required for search mode)
            url: URL to fetch (required for fetch mode)
            max_results: Maximum search results (default: 5, max: 20)

        Returns:
            ToolResult with search results or fetched content
        """
        if mode == "search":
            return self._search(query, max_results)
        elif mode == "fetch":
            return self._fetch(url)
        else:
            return ToolResult.error_result(
                f"Invalid mode: '{mode}'. Use 'search' or 'fetch'",
                suggestions=[
                    "Use mode='search' with query parameter for web search",
                    "Use mode='fetch' with url parameter to get page content",
                ],
            )

    def _search(self, query: Optional[str], max_results: int) -> ToolResult:
        """Search the web using DuckDuckGo.

        Args:
            query: Search query
            max_results: Maximum number of results

        Returns:
            ToolResult with search results
        """
        if not query or not query.strip():
            return ToolResult.error_result(
                "Query is required for search mode",
                suggestions=["Provide a search query: mode='search', query='your search'"],
            )

        # Clamp max_results
        max_results = max(1, min(max_results, 20))

        try:
            from duckduckgo_search import DDGS

            results = []
            with DDGS() as ddgs:
                for r in ddgs.text(query, max_results=max_results):
                    results.append({
                        "title": r.get("title", ""),
                        "url": r.get("href", ""),
                        "snippet": r.get("body", ""),
                    })

            if not results:
                return ToolResult.success_result(
                    data={"query": query, "results": [], "count": 0},
                    suggestions=["Try a different search query", "Use broader terms"],
                )

            # Generate suggestions based on results
            suggestions = [
                f"Found {len(results)} results",
                "Use web(mode='fetch', url='...') to get full content of a page",
            ]

            return ToolResult.success_result(
                data={
                    "query": query,
                    "results": results,
                    "count": len(results),
                },
                suggestions=suggestions,
            )

        except Exception as e:
            log.error(f"Web search error: {e}")
            return ToolResult.error_result(
                f"Search failed: {str(e)}",
                suggestions=["Check internet connection", "Try a simpler query"],
            )

    def _fetch(self, url: Optional[str]) -> ToolResult:
        """Fetch and parse content from a URL.

        Args:
            url: URL to fetch

        Returns:
            ToolResult with page content as markdown
        """
        if not url or not url.strip():
            return ToolResult.error_result(
                "URL is required for fetch mode",
                suggestions=["Provide a URL: mode='fetch', url='https://...'"],
            )

        # Basic URL validation
        if not url.startswith(("http://", "https://")):
            url = "https://" + url

        try:
            import requests
            import html2text

            # Fetch the page
            response = requests.get(
                url,
                timeout=30,
                headers={
                    "User-Agent": "Mozilla/5.0 (compatible; Rove/1.0; +https://github.com/mendyEdri/emdash)",
                },
                allow_redirects=True,
            )
            response.raise_for_status()

            # Get content type
            content_type = response.headers.get("Content-Type", "").lower()

            # Handle non-HTML content
            if "text/html" not in content_type and "application/xhtml" not in content_type:
                # For non-HTML, return raw text (truncated)
                content = response.text[:10000]
                if len(response.text) > 10000:
                    content += "\n\n[Content truncated...]"

                return ToolResult.success_result(
                    data={
                        "url": url,
                        "content": content,
                        "content_type": content_type,
                        "length": len(content),
                    },
                    suggestions=["Content returned as plain text (not HTML)"],
                )

            # Convert HTML to markdown
            h = html2text.HTML2Text()
            h.ignore_links = False
            h.ignore_images = True
            h.ignore_emphasis = False
            h.body_width = 0  # No line wrapping
            h.skip_internal_links = True
            h.inline_links = True

            content = h.handle(response.text)

            # Clean up excessive whitespace
            import re
            content = re.sub(r'\n{3,}', '\n\n', content)
            content = content.strip()

            # Truncate if too long
            original_length = len(content)
            if len(content) > 15000:
                content = content[:15000] + "\n\n[Content truncated...]"

            return ToolResult.success_result(
                data={
                    "url": url,
                    "content": content,
                    "content_type": content_type,
                    "length": len(content),
                    "truncated": original_length > 15000,
                },
                suggestions=[
                    "Content converted to markdown",
                    "Use web(mode='search', query='...') to find related pages",
                ],
            )

        except requests.exceptions.Timeout:
            return ToolResult.error_result(
                f"Request timed out for {url}",
                suggestions=["Try again later", "Check if the URL is accessible"],
            )
        except requests.exceptions.HTTPError as e:
            return ToolResult.error_result(
                f"HTTP error {e.response.status_code}: {url}",
                suggestions=["Check if the URL is correct", "The page may require authentication"],
            )
        except requests.exceptions.RequestException as e:
            return ToolResult.error_result(
                f"Failed to fetch URL: {str(e)}",
                suggestions=["Check internet connection", "Verify the URL is valid"],
            )
        except Exception as e:
            log.error(f"Web fetch error: {e}")
            return ToolResult.error_result(
                f"Fetch failed: {str(e)}",
                suggestions=["Try a different URL"],
            )

    def get_schema(self) -> dict:
        """Return OpenAI function calling schema."""
        return self._make_schema(
            properties={
                "mode": {
                    "type": "string",
                    "enum": ["search", "fetch"],
                    "description": "Operation mode: 'search' to search the web, 'fetch' to get URL content",
                },
                "query": {
                    "type": "string",
                    "description": "Search query (required when mode='search')",
                },
                "url": {
                    "type": "string",
                    "description": "URL to fetch content from (required when mode='fetch')",
                },
                "max_results": {
                    "type": "integer",
                    "default": 5,
                    "description": "Maximum number of search results (1-20, only for search mode)",
                },
            },
            required=["mode"],
        )
