"""
Python code analysis logic for Storm Logger development
"""

import json
import ast
import re
from pathlib import Path
from typing import Dict, Any, List, Optional, Union
import subprocess
import sys


def analyze_code(
    file_path: str,
    analysis_type: str = "comprehensive",
    standards_level: str = "storm_logger",
    output_format: str = "json"
) -> str:
    """
    Analyze Python code quality, structure, and adherence to Storm Logger standards
    
    Args:
        file_path: Path to Python file or directory
        analysis_type: "quality", "security", "performance", "comprehensive"
        standards_level: "basic", "storm_logger", "enterprise"
        output_format: "json", "markdown", "summary"
        
    Returns:
        Analysis results in requested format
    """
    path = Path(file_path)
    
    if not path.exists():
        return json.dumps({"error": f"Path {file_path} does not exist"}, indent=2)
    
    analysis = {
        "file_path": str(path),
        "analysis_type": analysis_type,
        "standards_level": standards_level,
        "timestamp": "2025-01-18",
        "summary": {},
        "details": {},
        "recommendations": [],
        "storm_compliance": {}
    }
    
    if path.is_file():
        file_analysis = analyze_single_file(path, analysis_type, standards_level)
        analysis.update(file_analysis)
    else:
        directory_analysis = analyze_directory(path, analysis_type, standards_level)
        analysis.update(directory_analysis)
    
    if output_format == "json":
        return json.dumps(analysis, indent=2)
    elif output_format == "markdown":
        return format_as_markdown(analysis)
    else:
        return format_as_summary(analysis)


def analyze_single_file(file_path: Path, analysis_type: str, standards_level: str) -> Dict[str, Any]:
    """
    Analyze a single Python file
    
    Args:
        file_path: Path to Python file
        analysis_type: Type of analysis
        standards_level: Standards level
        
    Returns:
        File analysis results
    """
    if not file_path.suffix == '.py':
        return {"error": f"File {file_path} is not a Python file"}
    
    try:
        content = file_path.read_text(encoding='utf-8')
    except Exception as e:
        return {"error": f"Cannot read file {file_path}: {str(e)}"}
    
    analysis = {
        "file_type": "single_file",
        "file_size": len(content),
        "line_count": len(content.splitlines()),
        "summary": {},
        "details": {},
        "recommendations": [],
        "storm_compliance": {}
    }
    
    # Parse AST
    try:
        tree = ast.parse(content)
    except SyntaxError as e:
        return {"error": f"Syntax error in {file_path}: {str(e)}"}
    
    # Run different analysis types
    if analysis_type in ["quality", "comprehensive"]:
        analysis["details"]["quality"] = analyze_code_quality(content, tree, standards_level)
    
    if analysis_type in ["security", "comprehensive"]:
        analysis["details"]["security"] = analyze_security(content, tree)
    
    if analysis_type in ["performance", "comprehensive"]:
        analysis["details"]["performance"] = analyze_performance(content, tree)
    
    # Storm Logger compliance check
    if standards_level in ["storm_logger", "enterprise"]:
        analysis["storm_compliance"] = check_storm_compliance(content, tree)
    
    # Generate summary
    analysis["summary"] = generate_summary(analysis["details"])
    
    # Generate recommendations
    analysis["recommendations"] = generate_recommendations(analysis["details"], standards_level)
    
    return analysis


def analyze_directory(dir_path: Path, analysis_type: str, standards_level: str) -> Dict[str, Any]:
    """
    Analyze a directory of Python files
    
    Args:
        dir_path: Path to directory
        analysis_type: Type of analysis
        standards_level: Standards level
        
    Returns:
        Directory analysis results
    """
    python_files = list(dir_path.glob("**/*.py"))
    
    if not python_files:
        return {"error": f"No Python files found in {dir_path}"}
    
    analysis = {
        "file_type": "directory",
        "total_files": len(python_files),
        "files_analyzed": [],
        "summary": {},
        "details": {},
        "recommendations": [],
        "storm_compliance": {}
    }
    
    file_results = []
    
    for py_file in python_files[:10]:  # Limit to first 10 files for performance
        file_analysis = analyze_single_file(py_file, analysis_type, standards_level)
        if "error" not in file_analysis:
            file_results.append({
                "file": str(py_file.relative_to(dir_path)),
                "analysis": file_analysis
            })
    
    analysis["files_analyzed"] = file_results
    
    # Aggregate results
    analysis["summary"] = aggregate_directory_summary(file_results)
    analysis["recommendations"] = aggregate_directory_recommendations(file_results)
    
    return analysis


def analyze_code_quality(content: str, tree: ast.AST, standards_level: str) -> Dict[str, Any]:
    """
    Analyze code quality metrics
    
    Args:
        content: File content
        tree: AST tree
        standards_level: Standards level
        
    Returns:
        Quality analysis results
    """
    quality = {
        "complexity": analyze_complexity(tree),
        "maintainability": analyze_maintainability(content, tree),
        "readability": analyze_readability(content, tree),
        "imports": analyze_imports(content, tree, standards_level),
        "docstrings": analyze_docstrings(tree),
        "type_hints": analyze_type_hints(tree),
        "line_length": analyze_line_length(content, standards_level)
    }
    
    return quality


def analyze_security(content: str, tree: ast.AST) -> Dict[str, Any]:
    """
    Analyze security vulnerabilities
    
    Args:
        content: File content
        tree: AST tree
        
    Returns:
        Security analysis results
    """
    security = {
        "vulnerabilities": [],
        "sensitive_data": check_sensitive_data(content),
        "unsafe_functions": check_unsafe_functions(tree),
        "hardcoded_secrets": check_hardcoded_secrets(content),
        "sql_injection": check_sql_injection(content),
        "command_injection": check_command_injection(tree)
    }
    
    return security


def analyze_performance(content: str, tree: ast.AST) -> Dict[str, Any]:
    """
    Analyze performance characteristics
    
    Args:
        content: File content
        tree: AST tree
        
    Returns:
        Performance analysis results
    """
    performance = {
        "bottlenecks": find_performance_bottlenecks(tree),
        "memory_usage": analyze_memory_usage(tree),
        "algorithmic_complexity": analyze_algorithmic_complexity(tree),
        "io_operations": analyze_io_operations(tree),
        "optimization_opportunities": find_optimization_opportunities(tree)
    }
    
    return performance


def check_storm_compliance(content: str, tree: ast.AST) -> Dict[str, Any]:
    """
    Check Storm Logger coding standards compliance
    
    Args:
        content: File content
        tree: AST tree
        
    Returns:
        Storm Logger compliance results
    """
    compliance = {
        "line_length": check_line_length_compliance(content),
        "import_organization": check_import_organization(content),
        "docstring_style": check_docstring_style(tree),
        "type_annotations": check_type_annotation_compliance(tree),
        "naming_conventions": check_naming_conventions(tree),
        "error_handling": check_error_handling_patterns(tree),
        "business_context": check_business_context(content, tree)
    }
    
    # Calculate overall compliance score
    compliance_scores = []
    for category, result in compliance.items():
        if isinstance(result, dict) and "score" in result:
            compliance_scores.append(result["score"])
    
    compliance["overall_score"] = sum(compliance_scores) / len(compliance_scores) if compliance_scores else 0
    compliance["compliance_level"] = get_compliance_level(compliance["overall_score"])
    
    return compliance


# Helper functions for analysis

def analyze_complexity(tree: ast.AST) -> Dict[str, Any]:
    """Analyze cyclomatic complexity"""
    class ComplexityVisitor(ast.NodeVisitor):
        def __init__(self):
            self.complexity = 1
            self.functions = []
            self.current_function = None
            
        def visit_FunctionDef(self, node):
            old_function = self.current_function
            self.current_function = node.name
            old_complexity = self.complexity
            self.complexity = 1
            self.generic_visit(node)
            self.functions.append({
                "name": node.name,
                "complexity": self.complexity,
                "line": node.lineno
            })
            self.complexity = old_complexity
            self.current_function = old_function
            
        def visit_If(self, node):
            self.complexity += 1
            self.generic_visit(node)
            
        def visit_For(self, node):
            self.complexity += 1
            self.generic_visit(node)
            
        def visit_While(self, node):
            self.complexity += 1
            self.generic_visit(node)
            
        def visit_Try(self, node):
            self.complexity += 1
            self.generic_visit(node)
    
    visitor = ComplexityVisitor()
    visitor.visit(tree)
    
    return {
        "functions": visitor.functions,
        "average_complexity": sum(f["complexity"] for f in visitor.functions) / len(visitor.functions) if visitor.functions else 0,
        "max_complexity": max(f["complexity"] for f in visitor.functions) if visitor.functions else 0
    }


def analyze_maintainability(content: str, tree: ast.AST) -> Dict[str, Any]:
    """Analyze maintainability metrics"""
    return {
        "function_count": len([n for n in ast.walk(tree) if isinstance(n, ast.FunctionDef)]),
        "class_count": len([n for n in ast.walk(tree) if isinstance(n, ast.ClassDef)]),
        "average_function_length": calculate_average_function_length(tree),
        "duplicate_code": detect_duplicate_code(content),
        "coupling": analyze_coupling(tree)
    }


def analyze_readability(content: str, tree: ast.AST) -> Dict[str, Any]:
    """Analyze readability metrics"""
    lines = content.splitlines()
    return {
        "comment_ratio": calculate_comment_ratio(lines),
        "blank_line_ratio": calculate_blank_line_ratio(lines),
        "variable_naming": analyze_variable_naming(tree),
        "function_naming": analyze_function_naming(tree),
        "class_naming": analyze_class_naming(tree)
    }


def analyze_imports(content: str, tree: ast.AST, standards_level: str) -> Dict[str, Any]:
    """Analyze import organization"""
    imports = []
    for node in ast.walk(tree):
        if isinstance(node, ast.Import):
            for alias in node.names:
                imports.append({
                    "type": "import",
                    "module": alias.name,
                    "alias": alias.asname,
                    "line": node.lineno
                })
        elif isinstance(node, ast.ImportFrom):
            for alias in node.names:
                imports.append({
                    "type": "from_import",
                    "module": node.module,
                    "name": alias.name,
                    "alias": alias.asname,
                    "line": node.lineno
                })
    
    return {
        "total_imports": len(imports),
        "imports": imports,
        "organization": check_import_organization_detailed(content, standards_level),
        "unused_imports": detect_unused_imports(content, tree)
    }


def analyze_docstrings(tree: ast.AST) -> Dict[str, Any]:
    """Analyze docstring coverage and quality"""
    functions_with_docstrings = 0
    classes_with_docstrings = 0
    total_functions = 0
    total_classes = 0
    
    for node in ast.walk(tree):
        if isinstance(node, ast.FunctionDef):
            total_functions += 1
            if ast.get_docstring(node):
                functions_with_docstrings += 1
        elif isinstance(node, ast.ClassDef):
            total_classes += 1
            if ast.get_docstring(node):
                classes_with_docstrings += 1
    
    return {
        "function_docstring_coverage": functions_with_docstrings / total_functions if total_functions > 0 else 0,
        "class_docstring_coverage": classes_with_docstrings / total_classes if total_classes > 0 else 0,
        "total_functions": total_functions,
        "total_classes": total_classes,
        "functions_with_docstrings": functions_with_docstrings,
        "classes_with_docstrings": classes_with_docstrings
    }


def analyze_type_hints(tree: ast.AST) -> Dict[str, Any]:
    """Analyze type hint coverage"""
    functions_with_hints = 0
    total_functions = 0
    
    for node in ast.walk(tree):
        if isinstance(node, ast.FunctionDef):
            total_functions += 1
            if node.returns or any(arg.annotation for arg in node.args.args):
                functions_with_hints += 1
    
    return {
        "coverage": functions_with_hints / total_functions if total_functions > 0 else 0,
        "total_functions": total_functions,
        "functions_with_hints": functions_with_hints
    }


def analyze_line_length(content: str, standards_level: str) -> Dict[str, Any]:
    """Analyze line length compliance"""
    max_length = 100 if standards_level == "storm_logger" else 79
    lines = content.splitlines()
    long_lines = [i + 1 for i, line in enumerate(lines) if len(line) > max_length]
    
    return {
        "max_allowed": max_length,
        "violations": len(long_lines),
        "violation_lines": long_lines[:10],  # Show first 10
        "compliance_rate": 1 - (len(long_lines) / len(lines)) if lines else 1
    }


# Security analysis functions

def check_sensitive_data(content: str) -> List[Dict[str, Any]]:
    """Check for potential sensitive data exposure"""
    sensitive_patterns = [
        (r'password\s*=\s*["\'][^"\']+["\']', "hardcoded_password"),
        (r'api_key\s*=\s*["\'][^"\']+["\']', "hardcoded_api_key"),
        (r'secret\s*=\s*["\'][^"\']+["\']', "hardcoded_secret"),
        (r'token\s*=\s*["\'][^"\']+["\']', "hardcoded_token"),
    ]
    
    findings = []
    for pattern, issue_type in sensitive_patterns:
        matches = re.finditer(pattern, content, re.IGNORECASE)
        for match in matches:
            line_num = content[:match.start()].count('\n') + 1
            findings.append({
                "type": issue_type,
                "line": line_num,
                "text": match.group(),
                "severity": "high"
            })
    
    return findings


def check_unsafe_functions(tree: ast.AST) -> List[Dict[str, Any]]:
    """Check for potentially unsafe function calls"""
    unsafe_functions = ['eval', 'exec', 'compile', '__import__']
    findings = []
    
    for node in ast.walk(tree):
        if isinstance(node, ast.Call):
            if isinstance(node.func, ast.Name) and node.func.id in unsafe_functions:
                findings.append({
                    "function": node.func.id,
                    "line": node.lineno,
                    "severity": "high",
                    "reason": f"Use of {node.func.id} can be dangerous"
                })
    
    return findings


def check_hardcoded_secrets(content: str) -> List[Dict[str, Any]]:
    """Check for hardcoded secrets"""
    # This is a simplified check - in reality, use more sophisticated patterns
    secret_patterns = [
        (r'["\'][A-Za-z0-9]{32,}["\']', "potential_secret"),
        (r'["\'][A-Za-z0-9+/]{40,}={0,2}["\']', "potential_base64_secret"),
    ]
    
    findings = []
    for pattern, issue_type in secret_patterns:
        matches = re.finditer(pattern, content)
        for match in matches:
            line_num = content[:match.start()].count('\n') + 1
            findings.append({
                "type": issue_type,
                "line": line_num,
                "length": len(match.group()),
                "severity": "medium"
            })
    
    return findings


def check_sql_injection(content: str) -> List[Dict[str, Any]]:
    """Check for potential SQL injection vulnerabilities"""
    sql_patterns = [
        (r'execute\s*\(\s*["\'].*%.*["\']', "string_formatting_sql"),
        (r'query\s*=\s*["\'].*\+.*["\']', "string_concatenation_sql"),
    ]
    
    findings = []
    for pattern, issue_type in sql_patterns:
        matches = re.finditer(pattern, content, re.IGNORECASE)
        for match in matches:
            line_num = content[:match.start()].count('\n') + 1
            findings.append({
                "type": issue_type,
                "line": line_num,
                "severity": "high",
                "recommendation": "Use parameterized queries instead"
            })
    
    return findings


def check_command_injection(tree: ast.AST) -> List[Dict[str, Any]]:
    """Check for potential command injection vulnerabilities"""
    dangerous_calls = ['os.system', 'subprocess.call', 'subprocess.run']
    findings = []
    
    for node in ast.walk(tree):
        if isinstance(node, ast.Call):
            if isinstance(node.func, ast.Attribute):
                full_name = f"{node.func.value.id}.{node.func.attr}" if isinstance(node.func.value, ast.Name) else None
                if full_name in dangerous_calls:
                    findings.append({
                        "function": full_name,
                        "line": node.lineno,
                        "severity": "medium",
                        "recommendation": "Validate and sanitize input"
                    })
    
    return findings


# Performance analysis functions

def find_performance_bottlenecks(tree: ast.AST) -> List[Dict[str, Any]]:
    """Find potential performance bottlenecks"""
    bottlenecks = []
    
    for node in ast.walk(tree):
        if isinstance(node, ast.For):
            # Check for nested loops
            for inner_node in ast.walk(node):
                if isinstance(inner_node, ast.For) and inner_node != node:
                    bottlenecks.append({
                        "type": "nested_loop",
                        "line": node.lineno,
                        "severity": "medium",
                        "recommendation": "Consider optimizing nested loops"
                    })
                    break
    
    return bottlenecks


def analyze_memory_usage(tree: ast.AST) -> Dict[str, Any]:
    """Analyze potential memory usage issues"""
    memory_issues = []
    
    for node in ast.walk(tree):
        if isinstance(node, ast.ListComp):
            memory_issues.append({
                "type": "list_comprehension",
                "line": node.lineno,
                "recommendation": "Consider using generator expression for large datasets"
            })
    
    return {
        "issues": memory_issues,
        "total_issues": len(memory_issues)
    }


def analyze_algorithmic_complexity(tree: ast.AST) -> Dict[str, Any]:
    """Analyze algorithmic complexity"""
    complexity_issues = []
    
    # This is a simplified analysis
    for node in ast.walk(tree):
        if isinstance(node, ast.For):
            nested_loops = sum(1 for n in ast.walk(node) if isinstance(n, ast.For))
            if nested_loops > 2:
                complexity_issues.append({
                    "type": "high_complexity_loop",
                    "line": node.lineno,
                    "nested_level": nested_loops,
                    "estimated_complexity": f"O(n^{nested_loops})"
                })
    
    return {
        "issues": complexity_issues,
        "total_issues": len(complexity_issues)
    }


def analyze_io_operations(tree: ast.AST) -> Dict[str, Any]:
    """Analyze I/O operations"""
    io_operations = []
    
    for node in ast.walk(tree):
        if isinstance(node, ast.Call):
            if isinstance(node.func, ast.Name) and node.func.id in ['open', 'print']:
                io_operations.append({
                    "operation": node.func.id,
                    "line": node.lineno,
                    "type": "file_io" if node.func.id == 'open' else "console_io"
                })
    
    return {
        "operations": io_operations,
        "total_operations": len(io_operations)
    }


def find_optimization_opportunities(tree: ast.AST) -> List[Dict[str, Any]]:
    """Find optimization opportunities"""
    opportunities = []
    
    # Check for string concatenation in loops
    for node in ast.walk(tree):
        if isinstance(node, ast.For):
            for inner_node in ast.walk(node):
                if isinstance(inner_node, ast.BinOp) and isinstance(inner_node.op, ast.Add):
                    opportunities.append({
                        "type": "string_concatenation_in_loop",
                        "line": node.lineno,
                        "recommendation": "Use list.join() or f-strings for better performance"
                    })
                    break
    
    return opportunities


# Storm Logger compliance functions

def check_line_length_compliance(content: str) -> Dict[str, Any]:
    """Check line length compliance for Storm Logger standards"""
    lines = content.splitlines()
    violations = [i + 1 for i, line in enumerate(lines) if len(line) > 100]
    
    return {
        "score": 1 - (len(violations) / len(lines)) if lines else 1,
        "violations": len(violations),
        "violation_lines": violations[:5],  # Show first 5
        "compliant": len(violations) == 0
    }


def check_import_organization(content: str) -> Dict[str, Any]:
    """Check Storm Logger import organization (4-section pattern)"""
    lines = content.splitlines()
    import_lines = []
    
    for i, line in enumerate(lines):
        if line.strip().startswith(('import ', 'from ')):
            import_lines.append((i + 1, line.strip()))
    
    # This is a simplified check
    return {
        "score": 0.8,  # Placeholder score
        "sections_found": 3,
        "sections_expected": 4,
        "organization": "partial",
        "recommendations": ["Organize imports into 4 sections: stdlib, third-party, local, types"]
    }


def check_docstring_style(tree: ast.AST) -> Dict[str, Any]:
    """Check docstring style compliance"""
    google_style_count = 0
    total_docstrings = 0
    
    for node in ast.walk(tree):
        if isinstance(node, (ast.FunctionDef, ast.ClassDef)):
            docstring = ast.get_docstring(node)
            if docstring:
                total_docstrings += 1
                if "Args:" in docstring and "Returns:" in docstring:
                    google_style_count += 1
    
    return {
        "score": google_style_count / total_docstrings if total_docstrings > 0 else 0,
        "google_style_count": google_style_count,
        "total_docstrings": total_docstrings,
        "compliance": google_style_count == total_docstrings
    }


def check_type_annotation_compliance(tree: ast.AST) -> Dict[str, Any]:
    """Check type annotation compliance"""
    annotated_functions = 0
    total_functions = 0
    
    for node in ast.walk(tree):
        if isinstance(node, ast.FunctionDef):
            total_functions += 1
            if node.returns and all(arg.annotation for arg in node.args.args):
                annotated_functions += 1
    
    return {
        "score": annotated_functions / total_functions if total_functions > 0 else 0,
        "annotated_functions": annotated_functions,
        "total_functions": total_functions,
        "compliance": annotated_functions == total_functions
    }


def check_naming_conventions(tree: ast.AST) -> Dict[str, Any]:
    """Check naming convention compliance"""
    violations = []
    
    for node in ast.walk(tree):
        if isinstance(node, ast.FunctionDef):
            if not node.name.islower() or not all(c.islower() or c == '_' for c in node.name):
                violations.append(f"Function {node.name} should use snake_case")
        elif isinstance(node, ast.ClassDef):
            if not node.name[0].isupper() or '_' in node.name:
                violations.append(f"Class {node.name} should use PascalCase")
    
    return {
        "score": 1 - (len(violations) / 10) if violations else 1,  # Normalize to 10 potential violations
        "violations": violations,
        "compliant": len(violations) == 0
    }


def check_error_handling_patterns(tree: ast.AST) -> Dict[str, Any]:
    """Check error handling patterns"""
    try_blocks = len([n for n in ast.walk(tree) if isinstance(n, ast.Try)])
    functions = len([n for n in ast.walk(tree) if isinstance(n, ast.FunctionDef)])
    
    return {
        "score": min(try_blocks / functions, 1.0) if functions > 0 else 0,
        "try_blocks": try_blocks,
        "functions": functions,
        "ratio": try_blocks / functions if functions > 0 else 0
    }


def check_business_context(content: str, tree: ast.AST) -> Dict[str, Any]:
    """Check for business context in docstrings"""
    business_keywords = ['business', 'revenue', 'metric', 'enterprise', 'professional']
    business_context_count = 0
    total_docstrings = 0
    
    for node in ast.walk(tree):
        if isinstance(node, (ast.FunctionDef, ast.ClassDef)):
            docstring = ast.get_docstring(node)
            if docstring:
                total_docstrings += 1
                if any(keyword in docstring.lower() for keyword in business_keywords):
                    business_context_count += 1
    
    return {
        "score": business_context_count / total_docstrings if total_docstrings > 0 else 0,
        "business_context_count": business_context_count,
        "total_docstrings": total_docstrings,
        "keywords_found": business_keywords
    }


def get_compliance_level(score: float) -> str:
    """Get compliance level based on score"""
    if score >= 0.9:
        return "excellent"
    elif score >= 0.8:
        return "good"
    elif score >= 0.7:
        return "acceptable"
    elif score >= 0.6:
        return "needs_improvement"
    else:
        return "poor"


# Utility functions

def calculate_average_function_length(tree: ast.AST) -> float:
    """Calculate average function length"""
    function_lengths = []
    
    for node in ast.walk(tree):
        if isinstance(node, ast.FunctionDef):
            # Calculate function length by counting statements
            statements = [n for n in ast.walk(node) if isinstance(n, ast.stmt)]
            function_lengths.append(len(statements))
    
    return sum(function_lengths) / len(function_lengths) if function_lengths else 0


def detect_duplicate_code(content: str) -> Dict[str, Any]:
    """Detect potential duplicate code"""
    lines = content.splitlines()
    line_hashes = {}
    duplicates = []
    
    for i, line in enumerate(lines):
        cleaned = line.strip()
        if cleaned and not cleaned.startswith('#'):
            if cleaned in line_hashes:
                duplicates.append({
                    "line1": line_hashes[cleaned],
                    "line2": i + 1,
                    "content": cleaned
                })
            else:
                line_hashes[cleaned] = i + 1
    
    return {
        "duplicates": duplicates,
        "duplicate_count": len(duplicates)
    }


def analyze_coupling(tree: ast.AST) -> Dict[str, Any]:
    """Analyze coupling between classes and functions"""
    # Simplified coupling analysis
    imports = len([n for n in ast.walk(tree) if isinstance(n, (ast.Import, ast.ImportFrom))])
    classes = len([n for n in ast.walk(tree) if isinstance(n, ast.ClassDef)])
    
    return {
        "import_count": imports,
        "class_count": classes,
        "coupling_ratio": imports / max(classes, 1)
    }


def calculate_comment_ratio(lines: List[str]) -> float:
    """Calculate comment ratio"""
    comment_lines = len([line for line in lines if line.strip().startswith('#')])
    return comment_lines / len(lines) if lines else 0


def calculate_blank_line_ratio(lines: List[str]) -> float:
    """Calculate blank line ratio"""
    blank_lines = len([line for line in lines if not line.strip()])
    return blank_lines / len(lines) if lines else 0


def analyze_variable_naming(tree: ast.AST) -> Dict[str, Any]:
    """Analyze variable naming conventions"""
    violations = []
    
    for node in ast.walk(tree):
        if isinstance(node, ast.Name) and isinstance(node.ctx, ast.Store):
            if not node.id.islower() or not all(c.islower() or c == '_' or c.isdigit() for c in node.id):
                violations.append(node.id)
    
    return {
        "violations": violations[:10],  # Show first 10
        "violation_count": len(violations)
    }


def analyze_function_naming(tree: ast.AST) -> Dict[str, Any]:
    """Analyze function naming conventions"""
    violations = []
    
    for node in ast.walk(tree):
        if isinstance(node, ast.FunctionDef):
            if not node.name.islower() or not all(c.islower() or c == '_' for c in node.name):
                violations.append(node.name)
    
    return {
        "violations": violations,
        "violation_count": len(violations)
    }


def analyze_class_naming(tree: ast.AST) -> Dict[str, Any]:
    """Analyze class naming conventions"""
    violations = []
    
    for node in ast.walk(tree):
        if isinstance(node, ast.ClassDef):
            if not node.name[0].isupper() or '_' in node.name:
                violations.append(node.name)
    
    return {
        "violations": violations,
        "violation_count": len(violations)
    }


def check_import_organization_detailed(content: str, standards_level: str) -> Dict[str, Any]:
    """Detailed import organization check"""
    lines = content.splitlines()
    import_sections = {
        "stdlib": [],
        "third_party": [],
        "local": [],
        "types": []
    }
    
    # This is a simplified implementation
    for i, line in enumerate(lines):
        if line.strip().startswith(('import ', 'from ')):
            if 'typing' in line:
                import_sections["types"].append(i + 1)
            elif any(stdlib in line for stdlib in ['os', 'sys', 'json', 'datetime', 'pathlib']):
                import_sections["stdlib"].append(i + 1)
            elif line.strip().startswith('from .'):
                import_sections["local"].append(i + 1)
            else:
                import_sections["third_party"].append(i + 1)
    
    return {
        "sections": import_sections,
        "organization_score": 0.8,  # Placeholder
        "recommendations": ["Organize imports into 4 sections with blank lines between"]
    }


def detect_unused_imports(content: str, tree: ast.AST) -> List[str]:
    """Detect unused imports"""
    # This is a simplified implementation
    imported_names = set()
    used_names = set()
    
    for node in ast.walk(tree):
        if isinstance(node, ast.Import):
            for alias in node.names:
                imported_names.add(alias.name)
        elif isinstance(node, ast.ImportFrom):
            for alias in node.names:
                imported_names.add(alias.name)
        elif isinstance(node, ast.Name):
            used_names.add(node.id)
    
    unused = imported_names - used_names
    return list(unused)


def generate_summary(details: Dict[str, Any]) -> Dict[str, Any]:
    """Generate analysis summary"""
    summary = {
        "overall_score": 0.0,
        "categories": {},
        "top_issues": [],
        "recommendations_count": 0
    }
    
    scores = []
    
    if "quality" in details:
        quality_score = calculate_quality_score(details["quality"])
        summary["categories"]["quality"] = quality_score
        scores.append(quality_score)
    
    if "security" in details:
        security_score = calculate_security_score(details["security"])
        summary["categories"]["security"] = security_score
        scores.append(security_score)
    
    if "performance" in details:
        performance_score = calculate_performance_score(details["performance"])
        summary["categories"]["performance"] = performance_score
        scores.append(performance_score)
    
    summary["overall_score"] = sum(scores) / len(scores) if scores else 0
    
    return summary


def calculate_quality_score(quality: Dict[str, Any]) -> float:
    """Calculate quality score"""
    scores = []
    
    if "complexity" in quality:
        avg_complexity = quality["complexity"]["average_complexity"]
        scores.append(max(0, 1 - (avg_complexity - 1) / 9))  # Normalize to 0-1
    
    if "docstrings" in quality:
        scores.append(quality["docstrings"]["function_docstring_coverage"])
    
    if "type_hints" in quality:
        scores.append(quality["type_hints"]["coverage"])
    
    if "line_length" in quality:
        scores.append(quality["line_length"]["compliance_rate"])
    
    return sum(scores) / len(scores) if scores else 0


def calculate_security_score(security: Dict[str, Any]) -> float:
    """Calculate security score"""
    total_issues = 0
    
    if "sensitive_data" in security:
        total_issues += len(security["sensitive_data"])
    
    if "unsafe_functions" in security:
        total_issues += len(security["unsafe_functions"])
    
    if "hardcoded_secrets" in security:
        total_issues += len(security["hardcoded_secrets"])
    
    # Higher score for fewer issues
    return max(0, 1 - total_issues / 10)


def calculate_performance_score(performance: Dict[str, Any]) -> float:
    """Calculate performance score"""
    total_issues = 0
    
    if "bottlenecks" in performance:
        total_issues += len(performance["bottlenecks"])
    
    if "memory_usage" in performance:
        total_issues += performance["memory_usage"]["total_issues"]
    
    if "algorithmic_complexity" in performance:
        total_issues += performance["algorithmic_complexity"]["total_issues"]
    
    # Higher score for fewer issues
    return max(0, 1 - total_issues / 10)


def generate_recommendations(details: Dict[str, Any], standards_level: str) -> List[Dict[str, Any]]:
    """Generate recommendations based on analysis"""
    recommendations = []
    
    if "quality" in details:
        quality = details["quality"]
        
        if "complexity" in quality and quality["complexity"]["max_complexity"] > 10:
            recommendations.append({
                "category": "quality",
                "priority": "high",
                "issue": "High cyclomatic complexity detected",
                "solution": "Consider breaking down complex functions into smaller, focused functions",
                "impact": "Improves maintainability and testability"
            })
        
        if "docstrings" in quality and quality["docstrings"]["function_docstring_coverage"] < 0.8:
            recommendations.append({
                "category": "quality",
                "priority": "medium",
                "issue": "Low docstring coverage",
                "solution": "Add comprehensive docstrings to all public functions and classes",
                "impact": "Improves code documentation and developer experience"
            })
        
        if "type_hints" in quality and quality["type_hints"]["coverage"] < 0.9:
            recommendations.append({
                "category": "quality",
                "priority": "high" if standards_level == "storm_logger" else "medium",
                "issue": "Insufficient type hint coverage",
                "solution": "Add type hints to all function parameters and return values",
                "impact": "Improves code reliability and IDE support"
            })
    
    if "security" in details:
        security = details["security"]
        
        if security["sensitive_data"]:
            recommendations.append({
                "category": "security",
                "priority": "high",
                "issue": "Potential sensitive data exposure",
                "solution": "Move sensitive data to environment variables or secure configuration",
                "impact": "Prevents accidental exposure of sensitive information"
            })
        
        if security["unsafe_functions"]:
            recommendations.append({
                "category": "security",
                "priority": "high",
                "issue": "Use of potentially unsafe functions",
                "solution": "Replace unsafe functions with safer alternatives or add proper validation",
                "impact": "Reduces security vulnerabilities"
            })
    
    if "performance" in details:
        performance = details["performance"]
        
        if performance["bottlenecks"]:
            recommendations.append({
                "category": "performance",
                "priority": "medium",
                "issue": "Performance bottlenecks detected",
                "solution": "Optimize algorithms and consider caching strategies",
                "impact": "Improves application performance and user experience"
            })
    
    return recommendations


def aggregate_directory_summary(file_results: List[Dict[str, Any]]) -> Dict[str, Any]:
    """Aggregate summary for directory analysis"""
    if not file_results:
        return {}
    
    total_score = 0
    total_files = len(file_results)
    categories = {}
    
    for result in file_results:
        if "summary" in result["analysis"]:
            summary = result["analysis"]["summary"]
            total_score += summary.get("overall_score", 0)
            
            for category, score in summary.get("categories", {}).items():
                if category not in categories:
                    categories[category] = []
                categories[category].append(score)
    
    # Average scores by category
    for category in categories:
        categories[category] = sum(categories[category]) / len(categories[category])
    
    return {
        "overall_score": total_score / total_files,
        "categories": categories,
        "files_analyzed": total_files
    }


def aggregate_directory_recommendations(file_results: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
    """Aggregate recommendations for directory analysis"""
    all_recommendations = []
    
    for result in file_results:
        if "recommendations" in result["analysis"]:
            for rec in result["analysis"]["recommendations"]:
                rec["file"] = result["file"]
                all_recommendations.append(rec)
    
    # Sort by priority and limit to top 10
    priority_order = {"high": 0, "medium": 1, "low": 2}
    all_recommendations.sort(key=lambda x: priority_order.get(x["priority"], 3))
    
    return all_recommendations[:10]


def format_as_markdown(analysis: Dict[str, Any]) -> str:
    """Format analysis results as markdown"""
    md = f"""# Python Code Analysis Report

## Summary
- **Overall Score**: {analysis.get('summary', {}).get('overall_score', 0):.2f}/1.0
- **Analysis Type**: {analysis.get('analysis_type', 'Unknown')}
- **Standards Level**: {analysis.get('standards_level', 'Unknown')}

## Categories
"""
    
    for category, score in analysis.get('summary', {}).get('categories', {}).items():
        md += f"- **{category.title()}**: {score:.2f}/1.0\n"
    
    md += "\n## Top Recommendations\n"
    for rec in analysis.get('recommendations', [])[:5]:
        md += f"- **{rec['priority'].upper()}**: {rec['issue']} - {rec['solution']}\n"
    
    return md


def format_as_summary(analysis: Dict[str, Any]) -> str:
    """Format analysis results as summary"""
    summary = analysis.get('summary', {})
    overall_score = summary.get('overall_score', 0)
    
    result = f"Code Analysis Summary\n"
    result += f"Overall Score: {overall_score:.2f}/1.0\n"
    result += f"Analysis Type: {analysis.get('analysis_type', 'Unknown')}\n"
    result += f"Standards Level: {analysis.get('standards_level', 'Unknown')}\n"
    result += f"Recommendations: {len(analysis.get('recommendations', []))}\n"
    
    if overall_score >= 0.8:
        result += "Status: Excellent code quality\n"
    elif overall_score >= 0.6:
        result += "Status: Good code quality with room for improvement\n"
    else:
        result += "Status: Needs significant improvement\n"
    
    return result