"""
AbuLang Fuzzy Matcher - Typo tolerance and command suggestions
"""

from difflib import SequenceMatcher, get_close_matches


class FuzzyMatcher:
    """Provides fuzzy matching for AbuLang commands and suggestions"""
    
    def __init__(self, commands_dict):
        """
        Initialize with AbuLang commands dictionary
        
        Args:
            commands_dict: Dictionary of valid commands from AbuLang
        """
        self.commands = commands_dict
        self.all_keywords = self._build_keyword_list()
    
    def _build_keyword_list(self):
        """Build a flat list of all valid keywords including aliases"""
        keywords = set()
        
        for cmd, info in self.commands.items():
            keywords.add(cmd)
            if "aliases" in info:
                keywords.update(info["aliases"])
        
        return list(keywords)
    
    def similarity(self, word1, word2):
        """
        Calculate similarity ratio between two words
        
        Returns:
            float: Similarity ratio between 0 and 1
        """
        return SequenceMatcher(None, word1.lower(), word2.lower()).ratio()
    
    def find_closest_match(self, word, threshold=0.6):
        """
        Find the closest matching command for a potentially misspelled word
        
        Args:
            word: The word to match
            threshold: Minimum similarity threshold (0-1)
        
        Returns:
            tuple: (matched_word, confidence) or (None, 0) if no match
        """
        if word in self.all_keywords:
            return word, 1.0
        
        # Use difflib for fast matching
        matches = get_close_matches(word, self.all_keywords, n=1, cutoff=threshold)
        
        if matches:
            best_match = matches[0]
            confidence = self.similarity(word, best_match)
            return best_match, confidence
        
        return None, 0.0
    
    def suggest_corrections(self, word, n=3, threshold=0.5):
        """
        Get multiple suggestions for a misspelled word
        
        Args:
            word: The word to match
            n: Number of suggestions to return
            threshold: Minimum similarity threshold
        
        Returns:
            list: List of (suggestion, confidence) tuples
        """
        if word in self.all_keywords:
            return [(word, 1.0)]
        
        matches = get_close_matches(word, self.all_keywords, n=n, cutoff=threshold)
        
        suggestions = []
        for match in matches:
            confidence = self.similarity(word, match)
            suggestions.append((match, confidence))
        
        return sorted(suggestions, key=lambda x: x[1], reverse=True)
    
    def correct_line(self, line, auto_correct=False):
        """
        Analyze a line and suggest or apply corrections
        
        Args:
            line: Line of AbuLang code
            auto_correct: If True, automatically apply best match
        
        Returns:
            tuple: (corrected_line, suggestions_dict)
        """
        words = line.split()
        if not words:
            return line, {}
        
        # Check first word (usually the command)
        first_word = words[0]
        match, confidence = self.find_closest_match(first_word)
        
        suggestions = {}
        corrected_line = line
        
        if match and match != first_word:
            if confidence >= 0.8 and auto_correct:
                # High confidence - auto-correct
                corrected_line = line.replace(first_word, match, 1)
                suggestions[first_word] = {
                    "correction": match,
                    "confidence": confidence,
                    "auto_corrected": True
                }
            elif confidence >= 0.6:
                # Medium confidence - suggest
                suggestions[first_word] = {
                    "correction": match,
                    "confidence": confidence,
                    "auto_corrected": False,
                    "alternatives": self.suggest_corrections(first_word, n=3)
                }
        
        return corrected_line, suggestions
