from typing import Dict, Any
import aiohttp
from bs4 import BeautifulSoup
from .base import Tool
import logging
import re

logger = logging.getLogger(__name__)

class BrowserTool(Tool):
    """Tool for browsing and extracting content from web pages"""

    def __init__(self):
        super().__init__(
            name="browser",
            description="Browse web pages and extract their content intelligently"
        )
        self.headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
        }

    async def execute(self, input_data: str) -> Dict[str, Any]:
        """Execute a web browsing task"""
        try:
            # Parse the input to extract URL and any specific instructions
            url = self._extract_url(input_data)
            if not url:
                return {
                    "success": False,
                    "error": "No valid URL found in input"
                }

            logger.info(f"Browsing URL: {url}")
            async with aiohttp.ClientSession() as session:
                async with session.get(url, headers=self.headers) as response:
                    if response.status == 200:
                        html = await response.text()
                        return await self._parse_content(html, url)

                    return {
                        "success": False,
                        "error": f"HTTP {response.status}: Unable to fetch page",
                        "url": url
                    }

        except Exception as e:
            logger.error(f"Error browsing: {str(e)}")
            return {
                "success": False,
                "error": f"Error during browsing: {str(e)}"
            }

    def _extract_url(self, input_data: str) -> str:
        """Extract URL from input string"""
        # Simple URL extraction using regex
        url_pattern = r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+'
        urls = re.findall(url_pattern, input_data)
        return urls[0] if urls else None

    async def _parse_content(self, html: str, url: str) -> Dict[str, Any]:
        """Parse and extract relevant content from HTML"""
        try:
            soup = BeautifulSoup(html, 'html.parser')

            # Extract title
            title = soup.title.string if soup.title else ""

            # Extract meta description
            meta_desc = ""
            meta_tag = soup.find("meta", {"name": "description"})
            if meta_tag:
                meta_desc = meta_tag.get("content", "")

            # Extract main content
            content = self._extract_main_content(soup)

            # Extract links
            links = self._extract_links(soup)

            return {
                "success": True,
                "url": url,
                "title": title,
                "description": meta_desc,
                "content": content,
                "links": links[:5]  # Limit to top 5 links
            }

        except Exception as e:
            logger.error(f"Error parsing content: {str(e)}")
            return {
                "success": False,
                "error": f"Error parsing content: {str(e)}",
                "url": url
            }

    def _extract_main_content(self, soup: BeautifulSoup) -> str:
        """Extract the main content from the page"""
        # Try different content containers in order of preference
        for container in ['main', 'article', 'div[role="main"]', '#content', '.content']:
            element = soup.select_one(container)
            if element:
                return self._clean_text(element.get_text())

        # Fallback to body text
        return self._clean_text(soup.body.get_text()) if soup.body else ""

    def _extract_links(self, soup: BeautifulSoup) -> list:
        """Extract relevant links from the page"""
        links = []
        for link in soup.find_all('a', href=True):
            href = link['href']
            text = self._clean_text(link.get_text())
            if href and text and not href.startswith('#'):
                links.append({
                    "url": href,
                    "text": text
                })
        return links

    def _clean_text(self, text: str) -> str:
        """Clean and normalize extracted text"""
        if not text:
            return ""
        # Remove extra whitespace and normalize text
        return " ".join(text.split())