"""
Interactive regex builder - construct patterns step by step
"""

import re


class RegexBuilder:
    """Build regex patterns interactively"""

    def __init__(self):
        self.parts = []
        self.description = []

    def add(self, pattern, desc):
        """Add a pattern part"""
        self.parts.append(pattern)
        self.description.append(desc)
        return self

    def literal(self, text):
        """Add literal text (auto-escaped)"""
        escaped = re.escape(text)
        self.parts.append(escaped)
        self.description.append(f"Literal: '{text}'")
        return self

    def digit(self, quantifier="one"):
        """Add digit pattern"""
        patterns = {
            "one": (r"\d", "Single digit"),
            "one_or_more": (r"\d+", "One or more digits"),
            "zero_or_more": (r"\d*", "Zero or more digits"),
            "optional": (r"\d?", "Optional digit"),
        }
        p, d = patterns.get(quantifier, patterns["one"])
        self.parts.append(p)
        self.description.append(d)
        return self

    def digits(self, min_count=None, max_count=None, exact=None):
        """Add specific number of digits"""
        if exact:
            self.parts.append(f"\\d{{{exact}}}")
            self.description.append(f"Exactly {exact} digits")
        elif min_count and max_count:
            self.parts.append(f"\\d{{{min_count},{max_count}}}")
            self.description.append(f"{min_count} to {max_count} digits")
        elif min_count:
            self.parts.append(f"\\d{{{min_count},}}")
            self.description.append(f"At least {min_count} digits")
        else:
            self.parts.append(r"\d+")
            self.description.append("One or more digits")
        return self

    def letter(self, case="any", quantifier="one"):
        """Add letter pattern"""
        case_patterns = {
            "any": "[a-zA-Z]",
            "lower": "[a-z]",
            "upper": "[A-Z]",
        }
        base = case_patterns.get(case, case_patterns["any"])

        quant_suffix = {
            "one": "",
            "one_or_more": "+",
            "zero_or_more": "*",
            "optional": "?",
        }
        suffix = quant_suffix.get(quantifier, "")

        self.parts.append(base + suffix)
        self.description.append(f"Letter ({case})" + (" (one or more)" if suffix == "+" else ""))
        return self

    def letters(self, min_count=None, max_count=None, exact=None, case="any"):
        """Add specific number of letters"""
        case_patterns = {
            "any": "[a-zA-Z]",
            "lower": "[a-z]",
            "upper": "[A-Z]",
        }
        base = case_patterns.get(case, case_patterns["any"])

        if exact:
            self.parts.append(f"{base}{{{exact}}}")
            self.description.append(f"Exactly {exact} letters")
        elif min_count and max_count:
            self.parts.append(f"{base}{{{min_count},{max_count}}}")
            self.description.append(f"{min_count} to {max_count} letters")
        elif min_count:
            self.parts.append(f"{base}{{{min_count},}}")
            self.description.append(f"At least {min_count} letters")
        else:
            self.parts.append(base + "+")
            self.description.append("One or more letters")
        return self

    def word(self):
        """Match a whole word"""
        self.parts.append(r"\w+")
        self.description.append("Word (letters, digits, underscore)")
        return self

    def whitespace(self, quantifier="one_or_more"):
        """Add whitespace"""
        patterns = {
            "one": (r"\s", "Single whitespace"),
            "one_or_more": (r"\s+", "One or more whitespace"),
            "zero_or_more": (r"\s*", "Zero or more whitespace"),
            "optional": (r"\s?", "Optional whitespace"),
        }
        p, d = patterns.get(quantifier, patterns["one_or_more"])
        self.parts.append(p)
        self.description.append(d)
        return self

    def any_of(self, chars):
        """Match any of the given characters"""
        # Escape special chars inside character class
        escaped = chars.replace(']', '\\]').replace('\\', '\\\\').replace('^', '\\^')
        if '-' in escaped:
            escaped = escaped.replace('-', '') + '-'  # Move hyphen to end
        self.parts.append(f"[{escaped}]")
        self.description.append(f"Any of: {chars}")
        return self

    def none_of(self, chars):
        """Match none of the given characters"""
        escaped = chars.replace(']', '\\]').replace('\\', '\\\\')
        if '-' in escaped:
            escaped = escaped.replace('-', '') + '-'
        self.parts.append(f"[^{escaped}]")
        self.description.append(f"Not any of: {chars}")
        return self

    def start(self):
        """Anchor to start of string"""
        self.parts.append("^")
        self.description.append("Start of string")
        return self

    def end(self):
        """Anchor to end of string"""
        self.parts.append("$")
        self.description.append("End of string")
        return self

    def word_boundary(self):
        """Add word boundary"""
        self.parts.append(r"\b")
        self.description.append("Word boundary")
        return self

    def optional(self, pattern):
        """Make a pattern optional"""
        if len(pattern) > 1:
            self.parts.append(f"(?:{pattern})?")
        else:
            self.parts.append(f"{pattern}?")
        self.description.append(f"Optional: {pattern}")
        return self

    def one_or_more(self, pattern):
        """One or more of a pattern"""
        if len(pattern) > 1:
            self.parts.append(f"(?:{pattern})+")
        else:
            self.parts.append(f"{pattern}+")
        self.description.append(f"One or more: {pattern}")
        return self

    def zero_or_more(self, pattern):
        """Zero or more of a pattern"""
        if len(pattern) > 1:
            self.parts.append(f"(?:{pattern})*")
        else:
            self.parts.append(f"{pattern}*")
        self.description.append(f"Zero or more: {pattern}")
        return self

    def either(self, *options):
        """Match either of the options"""
        escaped = [re.escape(opt) if not any(c in opt for c in r'\[](){}|^$.*+?') else opt for opt in options]
        self.parts.append(f"(?:{'|'.join(escaped)})")
        self.description.append(f"Either: {' or '.join(options)}")
        return self

    def group(self, pattern, name=None):
        """Create a capture group"""
        if name:
            self.parts.append(f"(?P<{name}>{pattern})")
            self.description.append(f"Capture group '{name}': {pattern}")
        else:
            self.parts.append(f"({pattern})")
            self.description.append(f"Capture group: {pattern}")
        return self

    def build(self):
        """Build the final pattern"""
        return "".join(self.parts)

    def explain(self):
        """Get explanation of the pattern"""
        return list(zip(self.parts, self.description))

    def test(self, text):
        """Test the pattern against text"""
        pattern = self.build()
        try:
            matches = re.findall(pattern, text)
            return {
                "pattern": pattern,
                "matches": matches,
                "count": len(matches)
            }
        except re.error as e:
            return {
                "pattern": pattern,
                "error": str(e),
                "matches": [],
                "count": 0
            }

    def clear(self):
        """Clear the builder"""
        self.parts = []
        self.description = []
        return self

    def undo(self):
        """Remove the last part"""
        if self.parts:
            self.parts.pop()
            self.description.pop()
        return self


# Convenience functions for common patterns
def build_email():
    """Build email pattern"""
    return (RegexBuilder()
            .add(r"[a-zA-Z0-9._%+-]+", "Username")
            .literal("@")
            .add(r"[a-zA-Z0-9.-]+", "Domain")
            .literal(".")
            .add(r"[a-zA-Z]{2,}", "TLD"))


def build_phone():
    """Build phone pattern"""
    return (RegexBuilder()
            .optional(r"\+?1[-.\s]?")
            .optional(r"\(?\d{3}\)?[-.\s]?")
            .digits(exact=3)
            .any_of("-. ")
            .digits(exact=4))


def build_url():
    """Build URL pattern"""
    return (RegexBuilder()
            .add(r"https?://", "Protocol")
            .optional(r"www\.")
            .add(r"[^\s]+", "Rest of URL"))
