from dosuby.src.interfaces.cms_enumeration_adapter import CMSEnumerationAdapter
from dosuby.src.factories.vulnerability_checker_factory import VulnerabilityCheckerFactory
from dosuby.src.core.domain.config import Config
import logging
from typing import Dict, Any, List, Optional

class VulnerabilityAwareCMSAdapter(CMSEnumerationAdapter):
    """CMS enumeration adapter with vulnerability detection capabilities"""
    
    def __init__(self) -> None:
        """Initialize the CMS enumeration adapter"""
        super().__init__()
        
        # Get configuration
        config = Config()
        self.check_vulnerabilities = config.check_cms_vulnerabilities
        self.vulnerability_checker_name = config.vulnerability_checker
        
        # Create vulnerability checker
        self.vulnerability_checker = VulnerabilityCheckerFactory.create(
            name=self.vulnerability_checker_name
        )
        
        self.logger = logging.getLogger("dosuby.cms_vulnerability")
        
    def get_result(self) -> Optional[Dict[str, Any]]:
        """Get the final detection result including vulnerability information
        
        Returns:
            Optional[Dict[str, Any]]: Detection result with vulnerabilities
        """
        cms_info = self.detect_cms()
        if cms_info and cms_info.get('detected'):
            version = self.detect_version()
            cms_info['version'] = version
            
            # Add vulnerability information if enabled
            if self.check_vulnerabilities and version:
                try:
                    self.logger.info(f"Checking vulnerabilities for {cms_info['cms']} {version}")
                    vulnerabilities = self.vulnerability_checker.check_cms_vulnerabilities(
                        cms_info['cms'], version
                    )
                    
                    # Get vulnerability summary
                    summary = self.vulnerability_checker.get_vulnerability_summary(vulnerabilities)
                    
                    # Add vulnerability information to the result
                    cms_info['vulnerabilities'] = vulnerabilities
                    cms_info['vulnerability_summary'] = summary
                    cms_info['is_vulnerable'] = summary['has_vulnerabilities']
                    cms_info['highest_severity'] = summary['highest_severity']
                    
                    # Log findings
                    if summary['has_vulnerabilities']:
                        self.logger.warning(
                            f"Found {summary['total']} vulnerabilities for {cms_info['cms']} {version} "
                            f"({summary['critical']} critical, {summary['high']} high, "
                            f"{summary['medium']} medium, {summary['low']} low)"
                        )
                    else:
                        self.logger.info(f"No vulnerabilities found for {cms_info['cms']} {version}")
                        
                except Exception as e:
                    self.logger.error(f"Error checking vulnerabilities: {str(e)}")
                    cms_info['vulnerability_error'] = str(e)
            
            return cms_info
        return None
        
    def to_string(self, result: Dict[str, Any]) -> str:
        """Convert the detection result to a string representation
        
        Args:
            result (Dict[str, Any]): The detection result
            
        Returns:
            str: String representation of the result
        """
        if not result:
            return None
            
        output = f"Detected {result['cms']}"
        
        if result.get('version'):
            output += f" v{result['version']}"
            
        if result.get('confidence'):
            output += f" (Confidence: {result['confidence']})"
            
        # Add vulnerability information if available
        if result.get('is_vulnerable'):
            summary = result.get('vulnerability_summary', {})
            
            vuln_info = f" - VULNERABLE: {summary.get('total', 0)} issues found"
            
            # Add severity counts
            critical_count = summary.get('critical', 0)
            high_count = summary.get('high', 0)
            
            if critical_count > 0:
                vuln_info += f" ({critical_count} critical"
                if high_count > 0:
                    vuln_info += f", {high_count} high"
                vuln_info += ")"
            elif high_count > 0:
                vuln_info += f" ({high_count} high)"
                
            # Add exploitability information
            exploitable_count = summary.get('exploitable', 0)
            if exploitable_count > 0:
                vuln_info += f", {exploitable_count} exploitable"
                
            output += vuln_info
                
        return output
    
    def _process(self, **kwargs):
        """Process the CMS detection
        
        This extends the base class _process method to include vulnerability checking
        
        Returns:
            dict or str: Detection result including vulnerability information
        """
        # Perform the standard CMS detection
        base_result = super()._process(**kwargs)
        
        # If the base implementation returns a string, keep it as is
        # This maintains compatibility with existing code
        if isinstance(base_result, str):
            return base_result
            
        # If we have a dictionary result, enhance it with vulnerabilities
        if isinstance(base_result, dict):
            # The result from get_result already includes vulnerability info
            detailed_result = self.get_result()
            
            if detailed_result:
                # Return either enhanced object or string depending on configuration
                config = Config()
                if getattr(config, 'return_detailed_vulnerabilities', False):
                    return detailed_result
                else:
                    return self.to_string(detailed_result)
            
        return base_result