"""
Main vulnerability checker class.
"""

import json
import logging
import time
from typing import Dict, List, Optional, Any, Type

from vulnerability_checker.checks import AVAILABLE_CHECKS, BaseCheck
from vulnerability_checker.models import VulnerabilityReport, CheckResult, CheckStatus


class VulnerabilityChecker:
    """
    Main class for checking vulnerabilities in Python code.
    """
    
    def __init__(self, config_path: Optional[str] = None):
        """
        Initialize the vulnerability checker.
        
        Args:
            config_path: Path to the configuration file
        """
        self.logger = logging.getLogger(__name__)
        self.config = self._load_config(config_path) if config_path else {}
    
    def _load_config(self, config_path: str) -> Dict[str, Any]:
        """
        Load configuration from file.
        
        Args:
            config_path: Path to the configuration file
            
        Returns:
            Dict[str, Any]: Configuration dictionary
        """
        try:
            with open(config_path, "r", encoding="utf-8") as f:
                return json.load(f)
        except Exception as e:
            self.logger.error(f"Error loading configuration: {str(e)}")
            return {}
    
    def run(
        self,
        target_path: str,
        checks: Optional[List[str]] = None,
        verbose: bool = False,
    ) -> VulnerabilityReport:
        """
        Run vulnerability checks.
        
        Args:
            target_path: Path to directory or file to check
            checks: List of checks to run (if None, all available checks are run)
            verbose: Detailed output
            
        Returns:
            VulnerabilityReport: Scan report
        """
        start_time = time.time()
        
        # Create report
        report = VulnerabilityReport(target_path=target_path)
        
        # Determine the list of checks to run
        checks_to_run = self._get_checks_to_run(checks)
        
        if verbose:
            print(f"Running {len(checks_to_run)} checks for {target_path}")
        
        # Run checks
        for check_name, check_class in checks_to_run.items():
            try:
                # Initialize check with configuration
                check_config = self.config.get(check_name, {})
                check_instance = check_class(config=check_config)
                
                if verbose:
                    print(f"Running check: {check_name}")
                
                # Run the check
                check_result, issues = check_instance.run(target_path, verbose=verbose)
                
                # Add check result to the report
                report.add_check_result(check_name, check_result)
                
                # Add found vulnerabilities to the report
                for issue in issues:
                    report.add_issue(issue)
                
                if verbose:
                    print(f"Check {check_name} completed: {check_result.status.value}")
                    print(f"Found vulnerabilities: {check_result.issues_count}")
                
            except Exception as e:
                # In case of error, add error information to the report
                self.logger.error(f"Error running check {check_name}: {str(e)}")
                error_result = CheckResult(
                    status=CheckStatus.ERROR,
                    issues_count=0,
                    message=f"Error running check: {str(e)}",
                )
                report.add_check_result(check_name, error_result)
        
        # Update scan statistics
        report.scan_duration_seconds = time.time() - start_time
        
        return report
    
    def _get_checks_to_run(
        self, selected_checks: Optional[List[str]] = None
    ) -> Dict[str, Type[BaseCheck]]:
        """
        Get the list of checks to run.
        
        Args:
            selected_checks: List of checks to run (if None, all available checks)
            
        Returns:
            Dict[str, Type[BaseCheck]]: Dictionary with checks to run
        """
        if selected_checks is None:
            # If no list is specified, return all available checks
            return AVAILABLE_CHECKS
        
        # Filter checks by list
        result = {}
        for check_name in selected_checks:
            if check_name in AVAILABLE_CHECKS:
                result[check_name] = AVAILABLE_CHECKS[check_name]
            else:
                self.logger.warning(f"Check {check_name} not found")
        
        return result 