"""
Debug why a regex doesn't match - the killer feature
"""

import re


def debug_no_match(pattern, text, expected=None):
    """
    Explain why a pattern doesn't match text (or doesn't match expected substring)
    Returns detailed diagnostics
    """
    diagnostics = {
        "pattern": pattern,
        "text": text[:200] + "..." if len(text) > 200 else text,
        "issues": [],
        "suggestions": [],
        "partial_matches": []
    }

    # Check if pattern is valid
    try:
        compiled = re.compile(pattern)
    except re.error as e:
        diagnostics["issues"].append(f"Invalid regex syntax: {e}")
        diagnostics["suggestions"].append("Check your regex syntax")
        return diagnostics

    # Check for actual matches
    matches = compiled.findall(text)
    if matches:
        diagnostics["actual_matches"] = matches[:5]
        if expected and expected not in str(matches):
            diagnostics["issues"].append(f"Pattern matches, but not '{expected}'")

    # Common issues to check

    # 1. Unescaped special characters
    special_chars = {
        '.': 'Dot matches ANY character. Use \\. for literal dot',
        '*': 'Asterisk is a quantifier. Use \\* for literal asterisk',
        '+': 'Plus is a quantifier. Use \\+ for literal plus',
        '?': 'Question mark is a quantifier. Use \\? for literal question mark',
        '[': 'Opens character class. Use \\[ for literal bracket',
        ']': 'Closes character class. Use \\] for literal bracket',
        '(': 'Opens group. Use \\( for literal parenthesis',
        ')': 'Closes group. Use \\) for literal parenthesis',
        '{': 'Opens quantifier. Use \\{ for literal brace',
        '}': 'Closes quantifier. Use \\} for literal brace',
        '^': 'Matches start of string. Use \\^ for literal caret',
        '$': 'Matches end of string. Use \\$ for literal dollar sign',
        '|': 'Alternation (OR). Use \\| for literal pipe',
        '\\': 'Escape character. Use \\\\ for literal backslash',
    }

    for char, explanation in special_chars.items():
        # Check if char is in text but might not be escaped in pattern
        if char in text:
            # Simple check: if char is in pattern without preceding backslash
            escaped = '\\' + char
            if char in pattern and escaped not in pattern:
                if char in '.+*?':
                    diagnostics["suggestions"].append(f"'{char}' in your pattern: {explanation}")

    # 2. Anchors issue
    if pattern.startswith('^') and not text.startswith(text.split()[0] if text else ''):
        diagnostics["suggestions"].append("Pattern starts with ^ (start anchor) - only matches at beginning of string/line")

    if pattern.endswith('$') and '$' not in pattern[:-1]:
        diagnostics["suggestions"].append("Pattern ends with $ (end anchor) - only matches at end of string/line")

    # 3. Case sensitivity
    if any(c.isupper() for c in pattern) and text.islower():
        diagnostics["suggestions"].append("Pattern has uppercase but text is lowercase. Try re.IGNORECASE flag")
    if any(c.islower() for c in pattern) and text.isupper():
        diagnostics["suggestions"].append("Pattern has lowercase but text is uppercase. Try re.IGNORECASE flag")

    # 4. Whitespace issues
    if '\\s' not in pattern and ' ' not in pattern:
        if ' ' in text and len(pattern) > 5:
            diagnostics["suggestions"].append("Text has spaces but pattern doesn't account for whitespace. Try adding \\s or spaces")

    # 5. Greedy matching
    if '.*' in pattern and '.*?' not in pattern:
        diagnostics["suggestions"].append("'.*' is greedy (matches as much as possible). Try '.*?' for non-greedy")
    if '.+' in pattern and '.+?' not in pattern:
        diagnostics["suggestions"].append("'.+' is greedy (matches as much as possible). Try '.+?' for non-greedy")

    # 6. Word boundaries
    if '\\b' not in pattern:
        # Check if they might need word boundaries
        words_in_pattern = re.findall(r'[a-zA-Z]{2,}', pattern)
        if words_in_pattern:
            diagnostics["suggestions"].append(f"Consider using \\b for word boundaries to avoid partial matches")

    # 7. Try partial matches - what parts of the pattern match?
    if not matches:
        # Try progressively shorter versions of the pattern
        for i in range(len(pattern) - 1, 0, -1):
            try:
                partial = pattern[:i]
                if re.search(partial, text):
                    diagnostics["partial_matches"].append({
                        "working_part": partial,
                        "failing_at": pattern[i:i+10] + "..." if len(pattern) > i+10 else pattern[i:]
                    })
                    break
            except re.error:
                continue

    # 8. Character class issues
    if '[' in pattern:
        # Check for common mistakes in character classes
        if '[-' in pattern and pattern.index('[-') > pattern.index('['):
            diagnostics["suggestions"].append("Hyphen in character class should be first or last, or escaped: [a-z] vs [a\\-z]")

    return diagnostics


def check_common_mistakes(pattern):
    """
    Check a pattern for common mistakes before they cause problems
    """
    warnings = []

    # Unescaped dots that probably should be escaped
    dot_contexts = re.finditer(r'(?<!\\)\.(?![*+?])', pattern)
    for match in dot_contexts:
        pos = match.start()
        context = pattern[max(0,pos-5):pos+5]
        # Check if it looks like it should be a literal dot (e.g., in domain names)
        if any(x in pattern for x in ['@', 'www', 'http', '.com', '.org']):
            warnings.append({
                "type": "unescaped_dot",
                "position": pos,
                "message": f"Unescaped '.' near '{context}' - matches ANY character. Did you mean '\\.'?"
            })

    # Potential catastrophic backtracking
    if re.search(r'\([^)]*\+[^)]*\)\+', pattern) or re.search(r'\([^)]*\*[^)]*\)\*', pattern):
        warnings.append({
            "type": "catastrophic_backtracking",
            "message": "Nested quantifiers detected (e.g., (a+)+). This can cause catastrophic backtracking!"
        })

    # Empty alternatives
    if '||' in pattern or pattern.startswith('|') or pattern.endswith('|'):
        warnings.append({
            "type": "empty_alternative",
            "message": "Empty alternative in pattern (||, starts with |, or ends with |). This matches empty string."
        })

    # Likely meant to escape
    if 'www.' in pattern and 'www\\.' not in pattern:
        warnings.append({
            "type": "unescaped_url_dot",
            "message": "'www.' should probably be 'www\\.' to match literal dot"
        })

    # Redundant escapes (not errors but noisy)
    redundant = re.findall(r'\\[a-zA-Z]', pattern)
    valid_escapes = {'d', 'D', 'w', 'W', 's', 'S', 'b', 'B', 'n', 'r', 't', 'f', 'v', 'A', 'Z'}
    for esc in redundant:
        if esc[1] not in valid_escapes:
            warnings.append({
                "type": "unnecessary_escape",
                "message": f"'{esc}' - '{esc[1]}' doesn't need escaping (but it still works)"
            })

    return warnings


def suggest_fix(pattern, text, expected_match):
    """
    Suggest how to fix a pattern to match expected text
    """
    suggestions = []

    # If expected_match is in text, try to figure out what pattern would match it
    if expected_match in text:
        # Start simple - escape special chars in expected match
        escaped = re.escape(expected_match)
        if re.search(escaped, text):
            suggestions.append({
                "suggestion": escaped,
                "explanation": "Escaped version of your expected match"
            })

        # Try with word boundaries
        bounded = r'\b' + escaped + r'\b'
        try:
            if re.search(bounded, text):
                suggestions.append({
                    "suggestion": bounded,
                    "explanation": "With word boundaries to match whole word only"
                })
        except re.error:
            pass

        # Try case insensitive
        suggestions.append({
            "suggestion": f"re.search(r'{escaped}', text, re.IGNORECASE)",
            "explanation": "Case-insensitive match"
        })

    return suggestions
