
"""Utility functions for feature branch and PR operations"""
import re
import time
from typing import Dict, Any, List, Optional
from utils.bmasterai_logging import get_logger, EventType, LogLevel

class FeaturePRWorker:
    """Helper class for feature branch and PR operations"""
    
    def __init__(self):
        self.logger = get_logger()
    
    def generate_branch_name(self, feature_prompt: str, prefix: str = "feature") -> str:
        """Generate a clean branch name from feature prompt"""
        # Clean the prompt
        clean_prompt = re.sub(r'[^a-zA-Z0-9\s-]', '', feature_prompt.lower())
        clean_prompt = re.sub(r'\s+', '-', clean_prompt.strip())
        
        # Limit length and add timestamp
        clean_prompt = clean_prompt[:40]
        timestamp = int(time.time()) % 10000  # Last 4 digits
        
        return f"{prefix}/{clean_prompt}-{timestamp}"
    
    def generate_commit_message(self, file_path: str, action: str, purpose: str) -> str:
        """Generate appropriate commit message"""
        action_map = {
            "create": "Add",
            "modify": "Update", 
            "delete": "Remove"
        }
        
        action_verb = action_map.get(action, "Change")
        return f"{action_verb} {file_path}: {purpose}"
    
    def format_pr_description(self, feature_plan: Dict[str, Any], original_prompt: str, files_modified: List[str]) -> str:
        """Format comprehensive PR description"""
        
        description = f"""## 🚀 Feature Implementation

**Original Request:** {original_prompt}

### 📋 Summary
{feature_plan.get('feature_analysis', {}).get('summary', 'Feature implementation')}

### 🔧 Implementation Details
{feature_plan.get('implementation_strategy', {}).get('approach', 'Implementation completed')}

### 📁 Files Changed
"""
        
        # Add modified files
        if files_modified:
            for file_path in files_modified:
                description += f"- `{file_path}`\n"
        
        # Add complexity info
        complexity = feature_plan.get('feature_analysis', {}).get('complexity', 'medium')
        description += f"\n**Complexity:** {complexity.title()}\n"
        
        # Add requirements
        requirements = feature_plan.get('feature_analysis', {}).get('requirements', [])
        if requirements:
            description += "\n### ✅ Requirements Addressed\n"
            for req in requirements:
                description += f"- {req}\n"
        
        # Add dependencies
        dependencies = feature_plan.get('dependencies', [])
        if dependencies:
            description += "\n### 📦 New Dependencies\n"
            for dep in dependencies:
                description += f"- **{dep['name']}** ({dep.get('version', 'latest')}) - {dep['purpose']}\n"
        
        # Add testing strategy
        testing = feature_plan.get('testing_strategy', {})
        if testing:
            description += "\n### 🧪 Testing Strategy\n"
            
            unit_tests = testing.get('unit_tests', [])
            if unit_tests:
                description += "**Unit Tests:**\n"
                for test in unit_tests:
                    description += f"- {test}\n"
            
            manual_tests = testing.get('manual_testing', [])
            if manual_tests:
                description += "\n**Manual Testing Steps:**\n"
                for i, test in enumerate(manual_tests, 1):
                    description += f"{i}. {test}\n"
        
        # Add potential issues
        issues = feature_plan.get('potential_issues', [])
        if issues:
            description += "\n### ⚠️ Potential Issues & Mitigations\n"
            for issue in issues:
                description += f"**Issue:** {issue['issue']}\n"
                description += f"**Mitigation:** {issue['mitigation']}\n\n"
        
        # Add integration points
        integration_points = feature_plan.get('implementation_strategy', {}).get('integration_points', [])
        if integration_points:
            description += "\n### 🔗 Integration Points\n"
            for point in integration_points:
                description += f"- {point}\n"
        
        description += "\n---\n*🤖 This PR was automatically generated by MCP GitHub Analyzer Feature Agent*"
        
        return description
    
    def validate_branch_name(self, branch_name: str) -> bool:
        """Validate branch name follows Git conventions"""
        # Check length
        if len(branch_name) > 100:
            return False
        
        # Check for invalid characters
        invalid_chars = r'[~^:?*\[\]\\]'
        if re.search(invalid_chars, branch_name):
            return False
        
        # Check for consecutive dots or slashes
        if '..' in branch_name or '//' in branch_name:
            return False
        
        # Check start/end characters
        if branch_name.startswith('.') or branch_name.endswith('.'):
            return False
        
        if branch_name.startswith('/') or branch_name.endswith('/'):
            return False
        
        return True
    
    def extract_repo_info(self, repo_url: str) -> Dict[str, str]:
        """Extract repository information from URL"""
        patterns = [
            r'https://github\.com/([^/]+)/([^/]+?)(?:\.git)?/?$',
            r'git@github\.com:([^/]+)/([^/]+?)(?:\.git)?$',
            r'github\.com/([^/]+)/([^/]+?)(?:\.git)?/?$'
        ]
        
        for pattern in patterns:
            match = re.match(pattern, repo_url.strip())
            if match:
                owner, repo = match.groups()
                return {
                    "owner": owner,
                    "repo": repo,
                    "full_name": f"{owner}/{repo}",
                    "url": f"https://github.com/{owner}/{repo}"
                }
        
        raise ValueError(f"Invalid GitHub repository URL: {repo_url}")
    
    def categorize_files_by_type(self, files: List[str]) -> Dict[str, List[str]]:
        """Categorize files by their type/purpose"""
        categories = {
            "source": [],
            "config": [],
            "documentation": [],
            "tests": [],
            "assets": [],
            "other": []
        }
        
        for file_path in files:
            file_lower = file_path.lower()
            
            if any(file_lower.endswith(ext) for ext in ['.py', '.js', '.ts', '.java', '.cpp', '.c', '.rs', '.go', '.php']):
                categories["source"].append(file_path)
            elif any(file_lower.endswith(ext) for ext in ['.json', '.yml', '.yaml', '.toml', '.ini', '.cfg', '.xml']):
                categories["config"].append(file_path)
            elif any(file_lower.endswith(ext) for ext in ['.md', '.rst', '.txt', '.doc', '.docx']):
                categories["documentation"].append(file_path)
            elif 'test' in file_lower or file_lower.endswith('.test.js') or file_lower.endswith('_test.py'):
                categories["tests"].append(file_path)
            elif any(file_lower.endswith(ext) for ext in ['.png', '.jpg', '.jpeg', '.gif', '.svg', '.ico', '.css', '.scss']):
                categories["assets"].append(file_path)
            else:
                categories["other"].append(file_path)
        
        return categories
    
    def estimate_implementation_time(self, feature_plan: Dict[str, Any]) -> Dict[str, Any]:
        """Estimate implementation time based on feature plan"""
        complexity = feature_plan.get('feature_analysis', {}).get('complexity', 'medium')
        files_count = len(feature_plan.get('files_to_modify', []))
        dependencies_count = len(feature_plan.get('dependencies', []))
        
        # Base time estimates in hours
        complexity_multiplier = {
            'low': 1.0,
            'medium': 2.0,
            'high': 4.0
        }
        
        base_time = complexity_multiplier.get(complexity, 2.0)
        file_time = files_count * 0.5  # 30 minutes per file
        dependency_time = dependencies_count * 1.0  # 1 hour per dependency
        
        total_hours = base_time + file_time + dependency_time
        
        return {
            "estimated_hours": round(total_hours, 1),
            "complexity_factor": complexity,
            "files_factor": files_count,
            "dependencies_factor": dependencies_count,
            "confidence": "medium" if total_hours < 8 else "low"
        }

# Singleton instance
_feature_pr_worker = None

def get_feature_pr_worker() -> FeaturePRWorker:
    """Get the singleton FeaturePRWorker instance"""
    global _feature_pr_worker
    if _feature_pr_worker is None:
        _feature_pr_worker = FeaturePRWorker()
    return _feature_pr_worker
