from langchain_community.utilities import DuckDuckGoSearchAPIWrapper
from typing import Dict, List, Any, Optional
from langchain_core.language_models import BaseLLM

from local_deep_research.web_search_engines.search_engine_base import BaseSearchEngine
from local_deep_research.web_search_engines.engines.full_search import FullSearchResults  # Import the FullSearchResults class
import logging
logger = logging.getLogger(__name__)

class DuckDuckGoSearchEngine(BaseSearchEngine):
    """DuckDuckGo search engine implementation with two-phase retrieval"""
    
    def __init__(self,
                max_results: int = 10,
                region: str = "us",
                safe_search: bool = True,
                llm: Optional[BaseLLM] = None,
                language: str = "English",
                include_full_content: bool = False,
                max_filtered_results=5):
        """
        Initialize the DuckDuckGo search engine.
        
        Args:
            max_results: Maximum number of search results
            region: Region code for search results
            safe_search: Whether to enable safe search
            llm: Language model for relevance filtering
            language: Language for content processing
            include_full_content: Whether to include full webpage content in results
        """
        # Initialize the BaseSearchEngine with LLM, max_filtered_results, and max_results
        super().__init__(llm=llm, max_filtered_results=max_filtered_results, max_results=max_results)
        self.region = region
        self.safe_search = safe_search
        self.language = language
        self.include_full_content = include_full_content
        
        # Initialize the DuckDuckGo wrapper
        self.engine = DuckDuckGoSearchAPIWrapper(
            region=region,
            max_results=max_results,
            safesearch="moderate" if safe_search else "off"
        )
        
        # Initialize FullSearchResults if full content is requested
        if include_full_content and llm:
            self.full_search = FullSearchResults(
                llm=llm,
                web_search=self.engine,
                language=language,
                max_results=max_results,
                region=region,
                time="y",
                safesearch="Moderate" if safe_search else "Off"
            )
    
    def run(self, query: str) -> List[Dict[str, Any]]:
        """
        Execute a search using DuckDuckGo with the two-phase approach.
        Respects config parameters:
        - SEARCH_SNIPPETS_ONLY: If True, only returns snippets without full content
        - SKIP_RELEVANCE_FILTER: If True, returns all results without filtering
        
        Args:
            query: The search query
            
        Returns:
            List of search results
        """
        logger.info("---Execute a search using DuckDuckGo---")
        
        # Implementation of the two-phase approach (from parent class)
        return super().run(query)
    
    def _get_previews(self, query: str) -> List[Dict[str, Any]]:
        """
        Get preview information (titles and snippets) for initial search results.
        
        Args:
            query: The search query
            
        Returns:
            List of preview dictionaries with 'id', 'title', and 'snippet' keys
        """
        try:
            # Get search results from DuckDuckGo
            results = self.engine.results(query, max_results=self.max_results)
            
            if not isinstance(results, list):
                return []
            
            # Process results to get previews
            previews = []
            for i, result in enumerate(results):
                preview = {
                    "id": result.get("link"),  # Use URL as ID for DDG
                    "title": result.get("title", ""),
                    "snippet": result.get("snippet", ""),
                    "link": result.get("link", "")
                }
                
                previews.append(preview)
            
            return previews
            
        except Exception as e:
            logger.error(f"Error getting DuckDuckGo previews: {e}")
            return []
    
    def _get_full_content(self, relevant_items: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
        """
        Get full content for the relevant items by using FullSearchResults.
        
        Args:
            relevant_items: List of relevant preview dictionaries
            
        Returns:
            List of result dictionaries with full content
        """
        # If we have FullSearchResults, use it to get full content
        if hasattr(self, 'full_search'):
            return self.full_search._get_full_content(relevant_items)
        
        # Otherwise, just return the relevant items without full content
        return relevant_items