"""
Command-line interface for regex-buddy
"""

import argparse
import sys
import re
from .patterns import get_pattern, list_patterns, test_pattern, explain_pattern, PATTERNS
from .custom import parse_description, suggest_patterns
from .debug import debug_no_match, check_common_mistakes, suggest_fix
from .cheatsheet import print_cheatsheet, print_escape_guide, quick_lookup
from .builder import RegexBuilder


def print_pattern(name, data, verbose=False):
    """Pretty print a pattern"""
    print(f"\n  Pattern: {data['pattern']}")
    print(f"  Description: {data.get('description', 'N/A')}")

    if verbose and 'explanation' in data:
        print("\n  Breakdown:")
        explanations = data['explanation'] if isinstance(data['explanation'], list) else [data['explanation']]
        for exp in explanations:
            print(f"    {exp}")

    if verbose and 'examples' in data:
        print("\n  Examples that match:")
        for ex in data['examples']:
            print(f"    {ex}")


def cmd_get(args):
    """Get a pattern by name"""
    pattern_data = get_pattern(args.name)

    if pattern_data:
        print(f"\n[{args.name}]")
        print_pattern(args.name, pattern_data, verbose=args.verbose)

        # Copy-paste ready
        print(f"\n  Python: r\"{pattern_data['pattern']}\"")
        print(f"  JavaScript: /{pattern_data['pattern']}/g")
    else:
        print(f"\nPattern '{args.name}' not found.")
        suggestions = suggest_patterns(args.name)
        if suggestions:
            print("\nDid you mean:")
            for s in suggestions:
                print(f"  - {s['name']}: {s['description']}")
        else:
            print("\nUse 'regex-buddy list' to see all available patterns.")


def cmd_list(args):
    """List all available patterns"""
    patterns = list_patterns()

    print("\nAvailable patterns:\n")
    print(f"  {'Name':<20} Description")
    print(f"  {'-'*20} {'-'*40}")

    for name, desc in sorted(patterns.items()):
        print(f"  {name:<20} {desc}")

    print(f"\nTotal: {len(patterns)} patterns")
    print("\nUse 'regex-buddy get <name>' for details")
    print("Use 'regex-buddy get <name> -v' for full explanation")


def cmd_test(args):
    """Test a pattern against text"""
    # Get pattern - either by name or direct regex
    if args.pattern in PATTERNS or get_pattern(args.pattern):
        pattern_data = get_pattern(args.pattern)
        pattern = pattern_data['pattern']
        print(f"\nUsing built-in pattern '{args.pattern}':")
        print(f"  {pattern}")
    else:
        pattern = args.pattern
        print(f"\nUsing pattern:")
        print(f"  {pattern}")

        # Check for common mistakes
        warnings = check_common_mistakes(pattern)
        if warnings:
            print("\n  Warnings:")
            for w in warnings:
                print(f"    - {w['message']}")

    # Get text to test against
    if args.text:
        text = args.text
    elif args.file:
        try:
            with open(args.file, 'r') as f:
                text = f.read()
        except FileNotFoundError:
            print(f"\nError: File '{args.file}' not found")
            return
    else:
        print("\nEnter text to test (Ctrl+D or Ctrl+Z to finish):")
        text = sys.stdin.read()

    # Run the test
    result = test_pattern(pattern, text)

    if result['success']:
        print(f"\nMatches found: {result['count']}")
        if result['matches']:
            print("\nMatches:")
            for i, match in enumerate(result['matches'][:20], 1):
                if isinstance(match, tuple):
                    match = match[0] if match else str(match)
                # Show context around match
                try:
                    idx = text.find(str(match))
                    if idx >= 0:
                        start = max(0, idx - 15)
                        end = min(len(text), idx + len(str(match)) + 15)
                        context = text[start:end].replace('\n', ' ')
                        if start > 0:
                            context = "..." + context
                        if end < len(text):
                            context = context + "..."
                        print(f"  {i}. {match}")
                        print(f"      Context: {context}")
                    else:
                        print(f"  {i}. {match}")
                except:
                    print(f"  {i}. {match}")
            if result['count'] > 20:
                print(f"  ... and {result['count'] - 20} more")
        else:
            # No matches - run debug
            print("\nNo matches. Running diagnostics...")
            diag = debug_no_match(pattern, text)
            if diag['suggestions']:
                print("\nSuggestions:")
                for s in diag['suggestions']:
                    print(f"  - {s}")
            if diag.get('partial_matches'):
                print("\nPartial match info:")
                for pm in diag['partial_matches']:
                    print(f"  - Pattern works up to: {pm['working_part']}")
                    print(f"    Fails at: {pm['failing_at']}")
    else:
        print(f"\nError in regex: {result['error']}")


def cmd_explain(args):
    """Explain a pattern"""
    # Check if it's a built-in pattern
    explanation = explain_pattern(args.pattern)

    if explanation:
        print(f"\nPattern: {explanation['pattern']}")
        print(f"Purpose: {explanation['description']}")
        print("\nBreakdown:")
        for part in explanation['explanation']:
            print(f"  {part}")
        print("\nExamples that match:")
        for ex in explanation['examples']:
            print(f"  {ex}")
    else:
        # Try to explain a custom regex
        pattern = args.pattern
        print(f"\nPattern: {pattern}")
        print("\nBreakdown:")

        # Parse and explain each part
        explanations = {
            r'\d': '\\d - Any digit (0-9)',
            r'\d+': '\\d+ - One or more digits',
            r'\D': '\\D - Any non-digit',
            r'\w': '\\w - Word character (letter, digit, underscore)',
            r'\w+': '\\w+ - One or more word characters',
            r'\W': '\\W - Non-word character',
            r'\s': '\\s - Whitespace (space, tab, newline)',
            r'\s+': '\\s+ - One or more whitespace',
            r'\S': '\\S - Non-whitespace',
            r'.': '. - Any character except newline',
            r'.*': '.* - Zero or more of any character (greedy)',
            r'.*?': '.*? - Zero or more of any character (lazy)',
            r'.+': '.+ - One or more of any character (greedy)',
            r'.+?': '.+? - One or more of any character (lazy)',
            r'^': '^ - Start of string',
            r'$': '$ - End of string',
            r'\b': '\\b - Word boundary',
            r'\B': '\\B - Not a word boundary',
            r'+': '+ - One or more of previous',
            r'*': '* - Zero or more of previous',
            r'?': '? - Zero or one of previous (optional)',
        }

        found_any = False
        for token, exp in explanations.items():
            if token in pattern:
                print(f"  {exp}")
                found_any = True

        # Look for character classes
        char_classes = re.findall(r'\[([^\]]+)\]', pattern)
        for cc in char_classes:
            print(f"  [{cc}] - Any character in: {cc}")
            found_any = True

        # Look for quantifiers
        quants = re.findall(r'\{(\d+)(?:,(\d*))?\}', pattern)
        for q in quants:
            if q[1] == '':
                print(f"  {{{q[0]},}} - {q[0]} or more times")
            elif q[1]:
                print(f"  {{{q[0]},{q[1]}}} - Between {q[0]} and {q[1]} times")
            else:
                print(f"  {{{q[0]}}} - Exactly {q[0]} times")
            found_any = True

        # Look for groups
        groups = re.findall(r'\(([^)]+)\)', pattern)
        for g in groups:
            if g.startswith('?:'):
                print(f"  (?:{g[2:]}) - Non-capturing group")
            elif g.startswith('?P<'):
                name = g[3:g.index('>')]
                print(f"  (?P<{name}>...) - Named capture group '{name}'")
            else:
                print(f"  ({g}) - Capture group")
            found_any = True

        if not found_any:
            print("  (Use a built-in pattern name for detailed explanation)")

        # Check for common mistakes
        warnings = check_common_mistakes(pattern)
        if warnings:
            print("\nPotential issues:")
            for w in warnings:
                print(f"  - {w['message']}")


def cmd_find(args):
    """Find a pattern by description"""
    description = " ".join(args.description)

    print(f"\nSearching for: {description}")

    # First try to parse as a custom description
    result = parse_description(description)

    if result.get('method') == 'matched_builtin':
        print(f"\nFound built-in pattern: {result['matched']}")
        pattern_data = get_pattern(result['matched'])
        print_pattern(result['matched'], pattern_data, verbose=True)
        print(f"\n  Python: r\"{pattern_data['pattern']}\"")
    elif result.get('pattern'):
        print(f"\nGenerated pattern (confidence: {result['confidence']}):")
        print(f"  {result['pattern']}")
        if isinstance(result.get('explanation'), list):
            print("\n  Breakdown:")
            for exp in result['explanation']:
                print(f"    {exp}")
    else:
        print("\nCouldn't generate a pattern from that description.")

    # Also show suggestions
    suggestions = suggest_patterns(description)
    if suggestions:
        print("\nRelated built-in patterns:")
        for s in suggestions:
            print(f"  - {s['name']}: {s['description']}")


def cmd_debug(args):
    """Debug why a pattern doesn't match"""
    pattern = args.pattern
    text = args.text

    print(f"\nDebugging pattern: {pattern}")
    print(f"Against text: {text[:100]}{'...' if len(text) > 100 else ''}")

    diag = debug_no_match(pattern, text, args.expected)

    if diag.get('actual_matches'):
        print(f"\nPattern DOES match: {diag['actual_matches']}")
        if args.expected:
            print(f"But you expected: {args.expected}")

    if diag['issues']:
        print("\nIssues found:")
        for issue in diag['issues']:
            print(f"  - {issue}")

    if diag['suggestions']:
        print("\nSuggestions:")
        for s in diag['suggestions']:
            print(f"  - {s}")

    if diag.get('partial_matches'):
        print("\nPartial match analysis:")
        for pm in diag['partial_matches']:
            print(f"  Pattern works up to: {pm['working_part']}")
            print(f"  Fails at: {pm['failing_at']}")

    if args.expected:
        fixes = suggest_fix(pattern, text, args.expected)
        if fixes:
            print("\nSuggested fixes to match your expected text:")
            for f in fixes:
                print(f"  {f['suggestion']}")
                print(f"    ({f['explanation']})")


def cmd_cheatsheet(args):
    """Show cheatsheet"""
    if args.escape:
        print_escape_guide()
    elif args.lookup:
        result = quick_lookup(args.lookup)
        if result:
            print(f"\n{result['term']}:")
            print(f"  Pattern: {result['pattern']}")
            print(f"  Example: {result['example']}")
        else:
            print(f"\nNo quick reference found for '{args.lookup}'")
            print("Try: digit, word, whitespace, start, end, boundary, optional, group, range")
    else:
        print_cheatsheet()


def cmd_build(args):
    """Interactive regex builder"""
    print("\nRegex Builder - Interactive Mode")
    print("Commands: digit, digits, letter, letters, word, literal <text>")
    print("          any <chars>, none <chars>, space, start, end, boundary")
    print("          optional <pattern>, either <a> <b>, group <pattern>")
    print("          show, test <text>, clear, undo, done")
    print()

    builder = RegexBuilder()

    while True:
        try:
            current = builder.build()
            prompt = f"[{current if current else 'empty'}]> "
            user_input = input(prompt).strip()
        except (EOFError, KeyboardInterrupt):
            print("\nExiting builder.")
            break

        if not user_input:
            continue

        parts = user_input.split()
        cmd = parts[0].lower()

        if cmd in ('done', 'exit', 'quit', 'q'):
            if current:
                print(f"\nFinal pattern: {current}")
                print(f"Python: r\"{current}\"")
            break
        elif cmd == 'show':
            print(f"\nCurrent pattern: {current}")
            exp = builder.explain()
            if exp:
                print("Parts:")
                for p, d in exp:
                    print(f"  {p} - {d}")
        elif cmd == 'clear':
            builder.clear()
            print("Cleared.")
        elif cmd == 'undo':
            builder.undo()
            print(f"Undone. Current: {builder.build()}")
        elif cmd == 'test' and len(parts) > 1:
            text = " ".join(parts[1:])
            result = builder.test(text)
            print(f"Matches: {result['count']}")
            if result['matches']:
                for m in result['matches'][:5]:
                    print(f"  - {m}")
        elif cmd == 'digit':
            builder.digit("one_or_more" if len(parts) > 1 and parts[1] == '+' else "one")
        elif cmd == 'digits':
            if len(parts) > 1:
                try:
                    n = int(parts[1])
                    builder.digits(exact=n)
                except:
                    builder.digits()
            else:
                builder.digits()
        elif cmd == 'letter':
            builder.letter(quantifier="one_or_more" if len(parts) > 1 and parts[1] == '+' else "one")
        elif cmd == 'letters':
            if len(parts) > 1:
                try:
                    n = int(parts[1])
                    builder.letters(exact=n)
                except:
                    builder.letters()
            else:
                builder.letters()
        elif cmd == 'word':
            builder.word()
        elif cmd == 'literal' and len(parts) > 1:
            builder.literal(" ".join(parts[1:]))
        elif cmd == 'any' and len(parts) > 1:
            builder.any_of(parts[1])
        elif cmd == 'none' and len(parts) > 1:
            builder.none_of(parts[1])
        elif cmd in ('space', 'whitespace'):
            builder.whitespace()
        elif cmd == 'start':
            builder.start()
        elif cmd == 'end':
            builder.end()
        elif cmd == 'boundary':
            builder.word_boundary()
        elif cmd == 'optional' and len(parts) > 1:
            builder.optional(parts[1])
        elif cmd == 'either' and len(parts) > 2:
            builder.either(*parts[1:])
        elif cmd == 'group' and len(parts) > 1:
            builder.group(parts[1], name=parts[2] if len(parts) > 2 else None)
        else:
            print(f"Unknown command: {cmd}")
            print("Try: digit, word, literal <text>, show, test <text>, done")


def cmd_interactive(args):
    """Interactive mode"""
    print("\nregex-buddy interactive mode")
    print("Commands: list, get <name>, test <pattern>, explain <pattern>")
    print("          find <description>, debug <pattern> <text>")
    print("          cheatsheet, build, quit")
    print()

    while True:
        try:
            user_input = input("regex> ").strip()
        except (EOFError, KeyboardInterrupt):
            print("\nGoodbye!")
            break

        if not user_input:
            continue

        parts = user_input.split(maxsplit=1)
        cmd = parts[0].lower()

        if cmd in ('quit', 'exit', 'q'):
            print("Goodbye!")
            break
        elif cmd == 'list':
            cmd_list(argparse.Namespace())
        elif cmd == 'get' and len(parts) > 1:
            cmd_get(argparse.Namespace(name=parts[1], verbose=True))
        elif cmd == 'test' and len(parts) > 1:
            pattern = parts[1]
            print("Enter text to test (empty line to finish):")
            lines = []
            while True:
                line = input()
                if not line:
                    break
                lines.append(line)
            text = "\n".join(lines)
            cmd_test(argparse.Namespace(pattern=pattern, text=text, file=None))
        elif cmd == 'explain' and len(parts) > 1:
            cmd_explain(argparse.Namespace(pattern=parts[1]))
        elif cmd == 'find' and len(parts) > 1:
            cmd_find(argparse.Namespace(description=parts[1].split()))
        elif cmd == 'debug' and len(parts) > 1:
            debug_parts = parts[1].split(maxsplit=1)
            if len(debug_parts) == 2:
                cmd_debug(argparse.Namespace(pattern=debug_parts[0], text=debug_parts[1], expected=None))
            else:
                print("Usage: debug <pattern> <text>")
        elif cmd == 'cheatsheet':
            print_cheatsheet()
        elif cmd == 'escape':
            print_escape_guide()
        elif cmd == 'build':
            cmd_build(argparse.Namespace())
        else:
            print("Unknown command. Try: list, get, test, explain, find, debug, cheatsheet, build, quit")


def main():
    parser = argparse.ArgumentParser(
        prog='regex-buddy',
        description='Plain English to Regex - Your friendly regex helper'
    )

    subparsers = parser.add_subparsers(dest='command', help='Commands')

    # List command
    list_parser = subparsers.add_parser('list', help='List all available patterns')

    # Get command
    get_parser = subparsers.add_parser('get', help='Get a pattern by name')
    get_parser.add_argument('name', help='Pattern name (e.g., email, phone, url)')
    get_parser.add_argument('-v', '--verbose', action='store_true', help='Show detailed explanation')

    # Test command
    test_parser = subparsers.add_parser('test', help='Test a pattern against text')
    test_parser.add_argument('pattern', help='Pattern name or regex')
    test_parser.add_argument('-t', '--text', help='Text to test against')
    test_parser.add_argument('-f', '--file', help='File to test against')

    # Explain command
    explain_parser = subparsers.add_parser('explain', help='Explain a pattern')
    explain_parser.add_argument('pattern', help='Pattern name or regex to explain')

    # Find command
    find_parser = subparsers.add_parser('find', help='Find pattern by description')
    find_parser.add_argument('description', nargs='+', help='Plain English description')

    # Debug command
    debug_parser = subparsers.add_parser('debug', help='Debug why a pattern doesn\'t match')
    debug_parser.add_argument('pattern', help='Regex pattern')
    debug_parser.add_argument('text', help='Text that should match')
    debug_parser.add_argument('-e', '--expected', help='Expected match substring')

    # Cheatsheet command
    cheat_parser = subparsers.add_parser('cheatsheet', aliases=['cheat', 'cs'], help='Show regex cheatsheet')
    cheat_parser.add_argument('-e', '--escape', action='store_true', help='Show escape guide')
    cheat_parser.add_argument('-l', '--lookup', help='Quick lookup a term')

    # Build command
    build_parser = subparsers.add_parser('build', help='Interactive regex builder')

    # Interactive command
    interactive_parser = subparsers.add_parser('interactive', aliases=['i'], help='Interactive mode')

    args = parser.parse_args()

    if args.command == 'list':
        cmd_list(args)
    elif args.command == 'get':
        cmd_get(args)
    elif args.command == 'test':
        cmd_test(args)
    elif args.command == 'explain':
        cmd_explain(args)
    elif args.command == 'find':
        cmd_find(args)
    elif args.command == 'debug':
        cmd_debug(args)
    elif args.command in ('cheatsheet', 'cheat', 'cs'):
        cmd_cheatsheet(args)
    elif args.command == 'build':
        cmd_build(args)
    elif args.command in ('interactive', 'i'):
        cmd_interactive(args)
    else:
        parser.print_help()


if __name__ == '__main__':
    main()
