"""
Configuration File Analyzer Implementation
"""

import os
import re
from typing import List, Dict, Any
from .base import SensitiveFileAnalyzer


class ConfigFileAnalyzer(SensitiveFileAnalyzer):
    """
    Configuration file analyzer for detecting plaintext passwords
    """
    
    def __init__(self):
        """Initialize the configuration file analyzer"""
        super().__init__()
        
    def analyze_files(self, file_paths: List[str]) -> List[Dict[str, Any]]:
        """
        Analyze configuration files for sensitive information
        
        Args:
            file_paths: List of file paths to analyze
            
        Returns:
            List of analysis results
        """
        findings = []
        
        for file_path in file_paths:
            if not os.path.exists(file_path):
                continue
                
            try:
                file_findings = self._analyze_single_file(file_path)
                findings.extend(file_findings)
            except Exception as e:
                print(f"Error analyzing file {file_path}: {e}")
                
        # Save results
        if findings:
            self._save_results(findings, f"sensitive_findings_{len(findings)}.json")
            
        return findings
    
    def get_analyzer_type(self) -> str:
        """
        Get analyzer type identifier
        
        Returns:
            "config_file_analyzer"
        """
        return "config_file_analyzer"
    
    def _analyze_single_file(self, file_path: str) -> List[Dict[str, Any]]:
        """
        Analyze a single file for sensitive information
        
        Args:
            file_path: Path to the file to analyze
            
        Returns:
            List of findings for the file
        """
        findings = []
        
        try:
            with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
                content = f.read()
                
            # Password-related keywords (case-insensitive)
            password_keywords = [
                "password", "passwd", "pwd", "secret", "api_key", "apikey",
                "access_key", "secret_key", "auth_token", "bearer_token",
                "connection_string", "db_password", "database_password",
                "mysql_password", "redis_password", "postgres_password",
                "mongodb_password", "sql_password"
            ]
            
            lines = content.split('\n')
            
            for line_number, line in enumerate(lines, 1):
                line = line.strip()
                
                for keyword in password_keywords:
                    # Case-insensitive search for keyword
                    if re.search(rf'\b{keyword}\b', line, re.IGNORECASE):
                        
                        # Check if it's an assignment statement
                        if '=' in line or ':' in line:
                            # Extract the value part (sanitized)
                            if '=' in line:
                                parts = line.split('=', 1)
                                key_part = parts[0].strip()
                                value_part = parts[1].strip() if len(parts) > 1 else ""
                            else:
                                parts = line.split(':', 1)
                                key_part = parts[0].strip()
                                value_part = parts[1].strip() if len(parts) > 1 else ""
                            
                            # Determine password type based on context
                            password_type = self._infer_password_type(keyword, line)
                            
                            # Find column position
                            keyword_pos = line.lower().find(keyword.lower())
                            
                            finding = {
                                "file": file_path,
                                "line_number": line_number,
                                "column": keyword_pos + 1,
                                "keyword": keyword,
                                "key_part": key_part,
                                "value_length": len(value_part),
                                "password_type": password_type,
                                "file_type": self._determine_file_type(file_path),
                                "sanitized_line": self._sanitize_line(line)
                            }
                            
                            findings.append(finding)
                            
        except Exception as e:
            print(f"Error reading file {file_path}: {e}")
            
        return findings
    
    def _infer_password_type(self, keyword: str, line: str) -> str:
        """
        Infer the type of password based on context
        
        Args:
            keyword: The keyword found
            line: The line containing the keyword
            
        Returns:
            Inferred password type
        """
        line_lower = line.lower()
        
        # Database types
        if "mysql" in line_lower or "mariadb" in line_lower:
            return "mysql"
        elif "postgres" in line_lower or "postgresql" in line_lower:
            return "postgresql"
        elif "redis" in line_lower:
            return "redis"
        elif "mongodb" in line_lower or "mongo" in line_lower:
            return "mongodb"
        elif "sql" in line_lower and "server" in line_lower:
            return "sqlserver"
        elif "oracle" in line_lower:
            return "oracle"
        
        # API/Service types
        elif "aws" in line_lower:
            return "aws"
        elif "azure" in line_lower:
            return "azure"
        elif "google" in line_lower or "gcp" in line_lower:
            return "gcp"
        elif "api" in keyword.lower():
            return "api"
        elif "token" in keyword.lower():
            return "token"
        
        # General types
        elif "db" in keyword.lower() or "database" in keyword.lower():
            return "database"
        elif "connection" in keyword.lower():
            return "connection_string"
        
        return "generic"
    
    def _determine_file_type(self, file_path: str) -> str:
        """
        Determine the type of configuration file
        
        Args:
            file_path: Path to the file
            
        Returns:
            File type identifier
        """
        filename = os.path.basename(file_path).lower()
        
        if filename.endswith('.json'):
            return "json"
        elif filename.endswith('.yml') or filename.endswith('.yaml'):
            return "yaml"
        elif filename.endswith('.xml'):
            return "xml"
        elif filename.endswith('.ini') or filename.endswith('.cfg') or filename.endswith('.conf'):
            return "ini"
        elif filename.endswith('.properties'):
            return "properties"
        elif filename.endswith('.env') or filename == '.env':
            return "env"
        elif filename.endswith('.config'):
            return "dotnet_config"
        elif filename == '.gitconfig':
            return "git_config"
        elif filename == 'credentials' and '.aws' in file_path:
            return "aws_credentials"
        else:
            return "unknown"
    
    def _sanitize_line(self, line: str) -> str:
        """
        Sanitize a line to hide actual password values
        
        Args:
            line: Original line
            
        Returns:
            Sanitized line
        """
        # Replace password values with [REDACTED]
        sanitized = re.sub(
            r'(password|passwd|pwd|secret|api_key|apikey|access_key|secret_key|auth_token|bearer_token)\s*[=:]\s*[^\s\n]+',
            r'\1 = [REDACTED]',
            line,
            flags=re.IGNORECASE
        )
        
        return sanitized