"""Google site preset with render support and Startpage fallback."""
import time
import random
import re
import logging

logger = logging.getLogger("iploop.sites.google")


class Google:
    RATE_LIMIT = 8
    _last_request = 0

    def __init__(self, client):
        self.client = client

    def _rate_limit(self):
        elapsed = time.time() - Google._last_request
        if elapsed < self.RATE_LIMIT:
            time.sleep(self.RATE_LIMIT - elapsed + random.uniform(0, 2))
        Google._last_request = time.time()

    def _validate_google_results(self, html: str) -> bool:
        """Check if we got real Google search results (not captcha/blocked)."""
        if not html:
            return False
        
        # Check for captcha/block indicators
        captcha_indicators = [
            'class="g-recaptcha"',
            '/recaptcha/',
            'data-recaptcha-action',
            'captcha-container',
            'unusual traffic from your computer',
            'blocked_form',
            'error-page',
            'automated queries'
        ]
        
        if any(indicator in html for indicator in captcha_indicators):
            return False
        
        # Check for actual search results
        result_indicators = [
            '<div class="g">',  # Search result container
            'data-ved=',        # Google's tracking
            '<h3 class="LC20lb',  # Result title
            'search?q=',        # Search URL
            '<span class="VuuXrf">',  # URL display
            'class="yuRUbf"'    # Result wrapper
        ]
        
        return any(indicator in html for indicator in result_indicators)

    def _extract_google_results(self, html: str) -> list:
        """Extract search results from Google HTML."""
        results = []
        
        # Pattern for search results
        pattern = r'<div class="g".*?</div>(?:\s*</div>)*'
        matches = re.finditer(pattern, html, re.DOTALL)
        
        for match in matches:
            result_html = match.group(0)
            
            # Extract title
            title_match = re.search(r'<h3[^>]*>(.*?)</h3>', result_html, re.DOTALL)
            title = re.sub(r'<[^>]+>', '', title_match.group(1)) if title_match else ""
            
            # Extract URL
            url_match = re.search(r'href="(/url\?q=)?([^"&]+)', result_html)
            url = url_match.group(2) if url_match else ""
            
            # Extract snippet
            snippet_match = re.search(r'<span[^>]*class="[^"]*st"[^>]*>(.*?)</span>', result_html, re.DOTALL)
            snippet = re.sub(r'<[^>]+>', '', snippet_match.group(1)) if snippet_match else ""
            
            if title and url:
                results.append({
                    "title": title.strip(),
                    "url": url.strip(),
                    "snippet": snippet.strip()
                })
        
        return results

    def _startpage_fallback(self, query: str, country: str = "US", num: int = 10) -> dict:
        """Use Startpage.com as fallback (proxies Google results without captcha)."""
        logger.info("Using Startpage fallback for Google search")
        
        import urllib.parse
        q = urllib.parse.quote_plus(query)
        
        # Startpage search with country preference
        country_param = f"&lui={country.lower()}"
        url = f"https://www.startpage.com/sp/search?query={q}&num={num}{country_param}"
        
        try:
            resp = self.client.fetch(url, country=country)
            
            # Extract results from Startpage
            results = self._extract_startpage_results(resp.text)
            
            return {
                "query": query,
                "country": country,
                "status": resp.status_code,
                "html": resp.text,
                "size_kb": len(resp.text) // 1024,
                "results": results,
                "source": "startpage"
            }
            
        except Exception as e:
            logger.error(f"Startpage fallback failed: {e}")
            return {
                "query": query,
                "country": country,
                "status": 500,
                "error": str(e),
                "source": "startpage"
            }

    def _extract_text(self, html: str) -> str:
        """Strip HTML tags and return clean text."""
        # Remove HTML tags
        text = re.sub(r'<[^>]+>', '', html)
        # Clean up whitespace
        text = re.sub(r'\s+', ' ', text).strip()
        return text

    def _extract_startpage_results(self, html: str) -> list:
        """Extract search results from Startpage HTML."""
        results = []
        
        # Test for multiple possible Startpage patterns
        patterns = [
            r'<a[^>]*class="[^"]*result-title[^"]*result-link[^"]*"[^>]*href="([^"]*)"[^>]*>.*?<h2[^>]*>(.*?)</h2>',
            r'<a[^>]*class="[^"]*result[^"]*"[^>]*href="([^"]*)"[^>]*>.*?<h2[^>]*class="[^"]*wgl-title[^"]*"[^>]*>(.*?)</h2>',
            r'<a class="w-gl__result-url"[^>]*href="([^"]*)"[^>]*>\s*<h3[^>]*>(.*?)</h3>',
            r'<h3[^>]*><a[^>]*href="([^"]*)"[^>]*>(.*?)</a></h3>'
        ]
        
        for pattern in patterns:
            matches = re.finditer(pattern, html, re.DOTALL | re.IGNORECASE)
            
            for match in matches:
                url = match.group(1).strip()
                title = self._extract_text(match.group(2)).strip()
                
                # Extract snippet if available
                snippet = ""
                # Look for description after the title
                title_pos = match.end()
                snippet_search = html[title_pos:title_pos + 500]
                snippet_match = re.search(r'<p[^>]*class="[^"]*description[^"]*"[^>]*>(.*?)</p>', snippet_search, re.DOTALL)
                if snippet_match:
                    snippet = self._extract_text(snippet_match.group(1)).strip()
                
                if title and url and url.startswith('http'):
                    results.append({
                        "title": title,
                        "url": url,
                        "snippet": snippet
                    })
            
            if results:  # If we found results with this pattern, stop trying others
                break
        
        return results

    def search(self, query, country="US", num=10, extract=True):
        """
        Google search with automatic render and Startpage fallback.
        Returns HTML with extracted results.
        """
        self._rate_limit()
        import urllib.parse
        q = urllib.parse.quote_plus(query)
        url = f"https://www.google.com/search?q={q}&num={num}&hl=en"
        
        # First try with rendering (better captcha bypass)
        try:
            if hasattr(self.client, 'render_fetch'):
                resp_html = self.client.render_fetch(url, country=country)
                
                if self._validate_google_results(resp_html):
                    results = self._extract_google_results(resp_html) if extract else []
                    return {
                        "query": query,
                        "country": country,
                        "status": 200,
                        "html": resp_html,
                        "size_kb": len(resp_html) // 1024,
                        "results": results,
                        "source": "google_render"
                    }
                else:
                    logger.warning("Google render returned captcha/blocked page")
            
            # Try regular HTTP request
            from ..fingerprint import chrome_fingerprint
            resp = self.client.fetch(url, country=country, headers=chrome_fingerprint(country))
            
            if resp.status_code == 200 and self._validate_google_results(resp.text):
                results = self._extract_google_results(resp.text) if extract else []
                return {
                    "query": query,
                    "country": country,
                    "status": resp.status_code,
                    "html": resp.text,
                    "size_kb": len(resp.text) // 1024,
                    "results": results,
                    "source": "google_http"
                }
            
        except Exception as e:
            logger.error(f"Google search failed: {e}")
        
        # Fall back to Startpage
        return self._startpage_fallback(query, country, num)

    def maps(self, query, country="US"):
        """Google Maps search with render support."""
        self._rate_limit()
        import urllib.parse
        url = f"https://www.google.com/maps/search/{urllib.parse.quote_plus(query)}"
        
        try:
            if hasattr(self.client, 'render_fetch'):
                html = self.client.render_fetch(url, country=country, wait_time=5)
                return {"query": query, "status": 200, "html": html, "source": "render"}
        except Exception as e:
            logger.error(f"Google Maps render failed: {e}")
        
        # Fallback to HTTP
        resp = self.client.fetch(url, country=country)
        return {"query": query, "status": resp.status_code, "html": resp.text, "source": "http"}
