"""
Pattern Matcher operations for Storm Logger MCP
Provides tools for creating and managing pattern matchers to avoid regex hell
"""

import json
from typing import Dict, List, Tuple, Optional


def create_pattern_matcher(
    name: str,
    description: str, 
    patterns: Dict[str, Tuple[str, str]],
    priority: str = "MEDIUM"
) -> str:
    """
    Generate a new PatternMatcher class for specific use case
    
    Args:
        name: Name of the matcher class (e.g., "PaymentCardMatcher")
        description: Description of what the matcher does
        patterns: Dictionary mapping pattern names to (regex, replacement) tuples
        priority: Priority level (CRITICAL, HIGH, MEDIUM, LOW)
        
    Returns:
        Generated Python code for the pattern matcher class
    """
    # Validate inputs
    if not name or not name[0].isupper():
        return "Error: Matcher name must start with uppercase letter"
    
    if not patterns:
        return "Error: At least one pattern must be provided"
    
    # Generate the class code
    code = f'''"""
{description}
"""

from typing import Dict, Optional, Tuple
from storm_logger.utils.patterns import PatternMatcher, PatternConfig, PatternPriority


class {name}(PatternMatcher):
    """
    {description}
    """
    
    def __init__(self, config: Optional[PatternConfig] = None):
        if config is None:
            config = PatternConfig(priority=PatternPriority.{priority})
        super().__init__(config)
    
    def _initialize_patterns(self) -> None:
        """Initialize patterns for this matcher"""
        self.compile_patterns()
    
    def get_pattern_definitions(self) -> Dict[str, Tuple[str, str]]:
        """Get pattern definitions for this matcher"""
        return {{'''
    
    # Add each pattern
    for i, (pattern_name, (regex, replacement)) in enumerate(patterns.items()):
        # Escape the regex string properly
        escaped_regex = regex.replace('\\', '\\\\').replace("'", "\\'")
        escaped_replacement = replacement.replace("'", "\\'")
        
        code += f"\n            '{pattern_name}': ("
        code += f"\n                r'{escaped_regex}',"
        code += f"\n                '{escaped_replacement}'"
        code += "\n            ),"
    
    code = code.rstrip(',')  # Remove trailing comma
    code += '''
        }
'''
    
    # Add optional validation method for specific matchers
    if "card" in name.lower() or "payment" in name.lower():
        code += '''
    
    def find_all(self, text: str) -> list:
        """Override to add Luhn validation for card numbers"""
        matches = super().find_all(text)
        
        # Filter card number matches through Luhn algorithm if applicable
        if any('card' in name.lower() or 'pan' in name.lower() for name in self.get_pattern_names()):
            filtered_matches = []
            for match in matches:
                if 'card' in match.pattern_name.lower() or match.pattern_name == 'pan':
                    # Extract digits and validate
                    import re
                    digits = re.sub(r'[^0-9]', '', match.matched_text)
                    if self._validate_luhn(digits):
                        filtered_matches.append(match)
                else:
                    filtered_matches.append(match)
            return filtered_matches
        
        return matches
    
    def _validate_luhn(self, card_number: str) -> bool:
        """Validate card number using Luhn algorithm"""
        if not card_number.isdigit() or len(card_number) < 13 or len(card_number) > 19:
            return False
        
        digits = [int(d) for d in card_number]
        checksum = 0
        
        # Double every second digit from right
        for i in range(len(digits) - 2, -1, -2):
            doubled = digits[i] * 2
            if doubled > 9:
                doubled = doubled - 9
            digits[i] = doubled
        
        return sum(digits) % 10 == 0
'''
    
    return code


def convert_regex_to_pattern(regex: str, replacement: str, pattern_name: str) -> str:
    """
    Convert a complex regex pattern to pattern matcher format
    
    Args:
        regex: Regular expression pattern
        replacement: Replacement text for matches
        pattern_name: Name for the pattern
        
    Returns:
        Dictionary entry for pattern matcher
    """
    # Validate regex
    try:
        import re
        re.compile(regex)
    except re.error as e:
        return f"Error: Invalid regex pattern - {str(e)}"
    
    # Generate pattern entry
    escaped_regex = regex.replace('\\', '\\\\').replace("'", "\\'")
    escaped_replacement = replacement.replace("'", "\\'")
    
    return f"""
# Add to your pattern matcher's get_pattern_definitions() method:
'{pattern_name}': (
    r'{escaped_regex}',
    '{escaped_replacement}'
),

# Example usage in a custom matcher:
class CustomMatcher(PatternMatcher):
    def get_pattern_definitions(self):
        return {{
            '{pattern_name}': (r'{escaped_regex}', '{escaped_replacement}'),
            # Add more patterns here
        }}
"""


def analyze_pattern_conflicts(patterns: List[str], test_data: str) -> str:
    """
    Analyze potential pattern conflicts and overlaps
    
    Args:
        patterns: List of regex patterns to analyze
        test_data: Sample text to test patterns against
        
    Returns:
        Analysis report with conflicts and suggestions
    """
    import re
    
    matches_by_pattern = {}
    all_matches = []
    
    # Compile and test each pattern
    for i, pattern in enumerate(patterns):
        try:
            compiled = re.compile(pattern)
            matches = list(compiled.finditer(test_data))
            matches_by_pattern[i] = matches
            
            for match in matches:
                all_matches.append({
                    'pattern_index': i,
                    'pattern': pattern,
                    'start': match.start(),
                    'end': match.end(),
                    'text': match.group(0)
                })
        except re.error as e:
            matches_by_pattern[i] = f"Error: {str(e)}"
    
    # Sort matches by position
    all_matches.sort(key=lambda x: (x['start'], x['end']))
    
    # Find overlaps
    overlaps = []
    for i in range(len(all_matches)):
        for j in range(i + 1, len(all_matches)):
            m1, m2 = all_matches[i], all_matches[j]
            
            # Check if they overlap
            if not (m1['end'] <= m2['start'] or m2['end'] <= m1['start']):
                overlaps.append({
                    'pattern1': m1['pattern'],
                    'pattern2': m2['pattern'],
                    'text1': m1['text'],
                    'text2': m2['text'],
                    'overlap_start': max(m1['start'], m2['start']),
                    'overlap_end': min(m1['end'], m2['end'])
                })
    
    # Generate report
    report = f"""Pattern Conflict Analysis
========================

Test Data: {test_data[:100]}{'...' if len(test_data) > 100 else ''}

Patterns Analyzed: {len(patterns)}
Total Matches Found: {len(all_matches)}
Overlapping Matches: {len(overlaps)}

"""
    
    if overlaps:
        report += "⚠️  Pattern Conflicts Detected:\n"
        report += "-" * 50 + "\n"
        
        for overlap in overlaps[:10]:  # Show first 10
            report += f"\nConflict between:\n"
            report += f"  Pattern 1: {overlap['pattern1'][:50]}...\n"
            report += f"    Matched: '{overlap['text1']}'\n"
            report += f"  Pattern 2: {overlap['pattern2'][:50]}...\n"
            report += f"    Matched: '{overlap['text2']}'\n"
            report += f"  Overlap region: positions {overlap['overlap_start']}-{overlap['overlap_end']}\n"
        
        report += "\n💡 Recommendations:\n"
        report += "1. Use PatternPriority to order patterns by importance\n"
        report += "2. Make patterns more specific to avoid false matches\n"
        report += "3. Use word boundaries (\\b) where appropriate\n"
        report += "4. Consider using negative lookahead/lookbehind\n"
        report += "5. Enable prevent_overlaps=True in PatternRegistry\n"
    else:
        report += "✅ No pattern conflicts detected!\n"
    
    # Show match summary
    report += f"\n\nMatch Summary:\n"
    report += "-" * 50 + "\n"
    
    for i, pattern in enumerate(patterns):
        if isinstance(matches_by_pattern[i], str):
            report += f"Pattern {i}: ERROR - {matches_by_pattern[i]}\n"
        else:
            count = len(matches_by_pattern[i])
            report += f"Pattern {i}: {count} matches\n"
            if count > 0:
                report += f"  Pattern: {pattern[:50]}...\n"
                report += f"  Sample matches: "
                samples = [m.group(0) for m in matches_by_pattern[i][:3]]
                report += ", ".join(f"'{s}'" for s in samples)
                if count > 3:
                    report += f" ... and {count - 3} more"
                report += "\n"
    
    return report


def generate_pattern_library_code(category: str) -> str:
    """
    Generate code for common pattern libraries
    
    Args:
        category: Category of patterns (financial, medical, security, etc.)
        
    Returns:
        Python code for pattern library
    """
    libraries = {
        "financial": {
            "description": "Financial data pattern matcher",
            "patterns": {
                "credit_card": (r'\b\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{3,6}\b', '[CARD]'),
                "iban": (r'[A-Z]{2}\d{2}[A-Z0-9]{1,30}', '[IBAN]'),
                "swift": (r'\b[A-Z]{6}[A-Z0-9]{2}(?:[A-Z0-9]{3})?\b', '[SWIFT]'),
                "routing_number": (r'\b(?:0[0-9]|1[0-2]|2[1-9]|3[0-2]|6[1-9]|7[0-2]|8[0-2]|9[0-1])\d{7}\b', '[ROUTING]'),
                "cvv": (r'(?:CVV|CVC|CSC)\s*[:=]?\s*\d{3,4}', '[CVV]'),
            }
        },
        "medical": {
            "description": "Medical and healthcare data pattern matcher",
            "patterns": {
                "mrn": (r'MRN\s*[:=]?\s*\d{6,10}', '[MRN]'),
                "npi": (r'\b\d{10}\b', '[NPI]'),
                "icd10": (r'\b[A-Z]\d{2}(?:\.\d{1,2})?\b', '[ICD10]'),
                "patient_id": (r'(?:PT|PAT)\d{6,8}', '[PATIENT_ID]'),
                "dea": (r'\b[A-Z]{2}\d{7}\b', '[DEA]'),
            }
        },
        "security": {
            "description": "Security token and credential pattern matcher",
            "patterns": {
                "jwt": (r'eyJ[a-zA-Z0-9\-_]+\.eyJ[a-zA-Z0-9\-_]+\.[a-zA-Z0-9\-_]+', '[JWT]'),
                "api_key": (r'(?:api[_-]?key|apikey)\s*[:=]\s*["\']?([a-zA-Z0-9\-_]{20,})', '[API_KEY]'),
                "bearer": (r'Bearer\s+[a-zA-Z0-9\-._~+/]+', '[BEARER]'),
                "basic_auth": (r'Basic\s+[a-zA-Z0-9+/]+=*', '[BASIC_AUTH]'),
                "oauth": (r'(?:oauth[_-]?token|access[_-]?token)\s*[:=]\s*["\']?([a-zA-Z0-9\-_]+)', '[OAUTH]'),
            }
        },
        "cloud": {
            "description": "Cloud service credential pattern matcher",
            "patterns": {
                "aws_access": (r'AKIA[0-9A-Z]{16}', '[AWS_KEY]'),
                "aws_secret": (r'(?:aws[_-]?secret)\s*[:=]\s*["\']?([a-zA-Z0-9+/]{40})', '[AWS_SECRET]'),
                "gcp_key": (r'AIza[0-9A-Za-z\-_]{35}', '[GCP_KEY]'),
                "azure_key": (r'(?:DefaultEndpointsProtocol=https;AccountName=)([^;]+);AccountKey=([^;]+)', '[AZURE]'),
                "github_token": (r'(?:ghp|gho|ghu|ghs|ghr)_[a-zA-Z0-9]{36,}', '[GITHUB]'),
            }
        }
    }
    
    if category not in libraries:
        available = ", ".join(libraries.keys())
        return f"Error: Unknown category '{category}'. Available categories: {available}"
    
    lib = libraries[category]
    class_name = f"{category.title()}PatternMatcher"
    
    return create_pattern_matcher(
        name=class_name,
        description=lib["description"],
        patterns=lib["patterns"],
        priority="HIGH" if category in ["security", "cloud"] else "MEDIUM"
    )