import re
import time
import logging
import asyncio
from datetime import datetime
from typing import List, Dict, Any
from urllib.parse import quote_plus


from app.core.config import settings
from selenium.webdriver.common.by import By
from app.shared.kafka_client.kafka_client import SearchKafkaClient
from app.shared.selenium_base.selenium_manager import SeleniumManager
from app.shared.common_models.search_models import SearchResult, SearchResponse


logger = logging.getLogger(__name__)

class GoogleSearchService:
    def __init__(self):
        self.kafka_client = SearchKafkaClient(
            bootstrap_servers=settings.KAFKA_BOOTSTRAP_SERVERS,
            consumer_group=settings.KAFKA_CONSUMER_GROUP
        )
    
    async def process_search_task(self, message: Dict[str, Any]):
        """Process a search task message"""
        try:
            task_id = message.get("id")
            keywords = message.get("keywords", [])
            
            logger.info(f"Processing Google search task: {task_id}")
            
            start_time = time.time()
            results = await self.search_google(keywords)
            processing_time = time.time() - start_time
            
            # Create response
            response = SearchResponse(
                task_id=task_id,
                platform="google",
                keywords=keywords,
                results=results,
                total_results=len(results),
                processing_time=processing_time,
                timestamp=datetime.utcnow()
            )
            
            # Send results back
            await self.kafka_client.send_search_result(
                task_id=task_id,
                platform="google",
                results=response.dict()
            )
            
            logger.info(f"Google search completed: {task_id}, found {len(results)} results")
            
        except Exception as e:
            logger.error(f"Error processing Google search task: {e}")
            await self.kafka_client.send_error_result(
                task_id=message.get("id", "unknown"),
                platform="google",
                error=str(e)
            )


    async def search_google(self, keywords: List[str], max_results: int = 20) -> List[SearchResult]:
        """Perform Google search"""
        results = []
        
        async with SeleniumManager(headless=True).driver_context() as selenium:
            try:
                # Build search query
                query = " ".join(keywords)
                encoded_query = quote_plus(query)
                search_url = f"https://www.google.com/search?q={encoded_query}&num={max_results}"
                
                logger.info(f"Searching Google for: {query}")
                
                #!!! Need Debugging
                # Navigate to Google search
                await selenium.navigate_to(search_url)
                
                # Wait for results to load
                await selenium.wait_for_page_load()
                await asyncio.sleep(15)
                
                # Google search result selectors
                result_selectors = [
                    'div.g',  # Main result container
                    'div[data-sokoban-container] div.g',  # Alternative container
                    'div.tF2Cxc'  # Another result container
                ] 

                result_elements = []
                for selector in result_selectors:
                    elements = await selenium.find_elements(selector)
                    if elements:
                        result_elements = elements
                        break
                 
                for element in result_elements:
                    try:
                        result = await self._extract_search_result(element)
                        if result:
                            results.append(result)
                    except Exception as e:
                        logger.warning(f"Error extracting result: {e}")
                        continue
                
                logger.info(f"Extracted {len(results)} results from Google")
                
            except Exception as e:
                logger.error(f"Error during Google search: {e}")
                raise
        
        return results
    

    async def _extract_search_result(self, element) -> SearchResult:
        """Extract search result from element"""
        try:
            title = "No title"
            url = "No URL"
            description = "No description"
            # Extract title and URL  
            title_element = element.find_element(By.CSS_SELECTOR, 'h3')
            if title_element:
                title = title_element.text
                link_element = title_element.find_element(By.XPATH, './..')
                url = link_element.get_attribute('href')

            # Extract snippet
            snippet_selectors = ['.VwiC3b', '.s3v9rd', '.st']
            for selector in snippet_selectors:
                try:
                    description_element = element.find_element(By.CSS_SELECTOR, selector)
                    description = description_element.text
                    break
                except:
                    continue 

            # # Extract displayed URL
            # try:
            #     cite_element = element.find_element(By.CSS_SELECTOR, 'cite')
            #     result['displayed_url'] = cite_element.text
            # except:
            #     pass
            
            # if result.get('url'):
            #     results.append(result)
            # Clean URL (remove Google redirect)
            url = self._clean_google_url(url)
            
            return SearchResult(
                title=title,
                url=url,
                description=description,
                snippet=description,
                source="google",
                metadata={
                    "search_engine": "google",
                    "extracted_at": datetime.utcnow().isoformat()
                }
            )
            
        except Exception as e:
            logger.warning(f"Error extracting search result: {e}")
            return None
    
    def _clean_google_url(self, url: str) -> str:
        """Clean Google redirect URL"""
        if url.startswith("/url?q="):
            # Extract actual URL from Google redirect
            match = re.search(r'/url\?q=([^&]+)', url)
            if match:
                return match.group(1)
        return url
