"""
Web Fetch Tool

Lightweight page fetcher using httpx + BeautifulSoup.
For static/server-rendered pages. Use Browser tool for JS-heavy pages.
"""

import logging
from typing import Dict, Any
from urllib.parse import urljoin, urlparse

from .base import BaseTool, ToolMetadata, ToolParameter, ToolPermission, ToolExecutionContext, ToolResult

logger = logging.getLogger(__name__)

DEFAULT_HEADERS = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Accept-Language': 'en-US,en;q=0.9',
    'DNT': '1',
    'Connection': 'keep-alive',
}


class FetchPageTool(BaseTool):
    """Fetch a web page and extract clean readable text."""

    def get_metadata(self) -> ToolMetadata:
        return ToolMetadata(
            name="FETCH_PAGE",
            description="Fetch a web page and extract clean, readable text. Uses HTTP (no browser). For JS-heavy pages, use the BROWSER tool.",
            category="network",
            parameters=[
                ToolParameter("url", "string", "URL to fetch", required=True),
                ToolParameter("extract_links", "boolean", "Include links in output", default=False),
                ToolParameter("max_length", "integer", "Max output length", default=10000),
                ToolParameter("headers", "object", "Additional HTTP headers"),
            ],
            permissions=[ToolPermission.NETWORK],
        )

    def execute(self, params: Dict[str, Any], context: ToolExecutionContext) -> ToolResult:
        url = params.get("url", "")
        extract_links = params.get("extract_links", False)
        max_length = params.get("max_length", 10000)
        extra_headers = params.get("headers", {})

        if not url:
            return ToolResult.fail("url is required")

        try:
            import httpx
            from bs4 import BeautifulSoup
        except ImportError:
            return ToolResult.fail("httpx and beautifulsoup4 are required")

        headers = {**DEFAULT_HEADERS, **extra_headers}

        try:
            with httpx.Client(follow_redirects=True, timeout=30) as client:
                response = client.get(url, headers=headers)
                response.raise_for_status()

            content_type = response.headers.get("content-type", "")

            if "text/html" in content_type or "application/xhtml" in content_type:
                soup = BeautifulSoup(response.text, "html.parser")

                # Remove noise
                for tag in soup.find_all(["script", "style", "nav", "footer", "header", "aside", "iframe"]):
                    tag.decompose()

                # Extract text
                text = soup.get_text(separator="\n", strip=True)
                # Clean up whitespace
                lines = [line.strip() for line in text.splitlines() if line.strip()]
                text = "\n".join(lines)

                output_parts = [text[:max_length]]

                # Extract links if requested
                if extract_links:
                    links = []
                    for a in soup.find_all("a", href=True):
                        href = a["href"]
                        link_text = a.get_text(strip=True)[:80]
                        abs_url = urljoin(url, href)
                        if abs_url.startswith(("http://", "https://")):
                            links.append(f"  [{link_text}]({abs_url})")
                    if links:
                        output_parts.append(f"\n\nLinks ({len(links)}):\n" + "\n".join(links[:50]))

                output = "\n".join(output_parts)
            else:
                # Non-HTML: return raw text
                output = response.text[:max_length]

            return ToolResult.ok(output, status_code=response.status_code, url=str(response.url))

        except httpx.HTTPStatusError as e:
            return ToolResult.fail(f"HTTP {e.response.status_code}: {e.response.reason_phrase}")
        except httpx.TimeoutException:
            return ToolResult.fail(f"Request timed out fetching {url}")
        except Exception as e:
            return ToolResult.fail(f"Error fetching page: {e}")


def get_all_tools():
    return [FetchPageTool]
