"""Code quality analysis utilities."""

import os
import re
from pathlib import Path
from typing import Dict, Any, List
from git import Repo


def count_todos_fixmes(repo_path: str) -> Dict[str, int]:
    """Count TODO and FIXME comments in the codebase."""
    todo_pattern = re.compile(r'#\s*(TODO|FIXME|XXX|HACK|NOTE):', re.IGNORECASE)
    
    counts = {"TODO": 0, "FIXME": 0, "XXX": 0, "HACK": 0, "NOTE": 0}
    
    # Common code extensions
    code_extensions = {
        ".py", ".js", ".ts", ".jsx", ".tsx", ".java", ".go", ".rs",
        ".c", ".cpp", ".h", ".hpp", ".rb", ".php", ".swift", ".kt"
    }
    
    try:
        repo_path_obj = Path(repo_path)
        for file_path in repo_path_obj.rglob("*"):
            if file_path.is_file() and file_path.suffix in code_extensions:
                # Skip common directories
                if any(part in file_path.parts for part in ["node_modules", "venv", ".git", "dist", "build"]):
                    continue
                
                try:
                    with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
                        for line in f:
                            match = todo_pattern.search(line)
                            if match:
                                keyword = match.group(1).upper()
                                if keyword in counts:
                                    counts[keyword] += 1
                except Exception:
                    continue
    except Exception as e:
        print(f"Error counting TODOs: {e}")
    
    return counts


def detect_test_files(changed_files: List[str]) -> bool:
    """Detect if any test files were changed."""
    test_indicators = [
        "test_", "_test.", "test.", ".test.", "spec.",
        "/tests/", "/test/", "__tests__", ".spec."
    ]
    
    for file_path in changed_files:
        file_lower = file_path.lower()
        if any(indicator in file_lower for indicator in test_indicators):
            return True
    
    return False


def analyze_file_sizes(repo_path: str) -> Dict[str, Any]:
    """Analyze file sizes in the repository."""
    code_extensions = {
        ".py", ".js", ".ts", ".jsx", ".tsx", ".java", ".go", ".rs",
        ".c", ".cpp", ".h", ".hpp", ".rb", ".php", ".swift", ".kt"
    }
    
    file_sizes = []
    total_lines = 0
    
    try:
        repo_path_obj = Path(repo_path)
        for file_path in repo_path_obj.rglob("*"):
            if file_path.is_file() and file_path.suffix in code_extensions:
                if any(part in file_path.parts for part in ["node_modules", "venv", ".git", "dist", "build"]):
                    continue
                
                try:
                    with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
                        lines = len(f.readlines())
                        file_sizes.append(lines)
                        total_lines += lines
                except Exception:
                    continue
    except Exception as e:
        print(f"Error analyzing file sizes: {e}")
    
    if not file_sizes:
        return {
            "total_files": 0,
            "total_lines": 0,
            "avg_file_size": 0,
            "largest_file": 0,
        }
    
    return {
        "total_files": len(file_sizes),
        "total_lines": total_lines,
        "avg_file_size": sum(file_sizes) / len(file_sizes),
        "largest_file": max(file_sizes),
    }


def categorize_commit_size(lines_changed: int) -> str:
    """Categorize commit by size."""
    if lines_changed < 10:
        return "tiny"
    elif lines_changed < 50:
        return "small"
    elif lines_changed < 200:
        return "medium"
    elif lines_changed < 500:
        return "large"
    else:
        return "massive"


def analyze_commit_quality(commit_data: Dict[str, Any]) -> Dict[str, Any]:
    """Analyze the quality of a commit."""
    message = commit_data.get("message", "")
    lines_changed = commit_data.get("lines_added", 0) + commit_data.get("lines_deleted", 0)
    files_changed = commit_data.get("files_changed", 0)
    
    quality_score = 0
    feedback = []
    
    # Message quality (40 points)
    if commit_data.get("is_clean", False):
        quality_score += 40
        feedback.append("Good commit message")
    else:
        feedback.append("Improve commit message clarity")
    
    # Size appropriateness (30 points)
    size_category = categorize_commit_size(lines_changed)
    if size_category in ["small", "medium"]:
        quality_score += 30
        feedback.append("Appropriate commit size")
    elif size_category == "tiny":
        quality_score += 20
        feedback.append("Very small commit")
    elif size_category == "large":
        quality_score += 15
        feedback.append("Large commit - consider breaking it up")
    else:  # massive
        quality_score += 5
        feedback.append("Massive commit - definitely break it up!")
    
    # Files changed (30 points)
    if files_changed <= 5:
        quality_score += 30
        feedback.append("Focused file changes")
    elif files_changed <= 15:
        quality_score += 20
        feedback.append("Moderate file changes")
    else:
        quality_score += 5
        feedback.append("Many files changed - be careful!")
    
    return {
        "quality_score": quality_score,
        "size_category": size_category,
        "feedback": feedback,
    }
