from ctf.utils import suggest_patterns
import pytest

# =====================================================================
# 1. Test Strategy Summary
# =====================================================================
# This suite verifies the `suggest_patterns` utility function which parses
# a sample flag string and generates a prioritized, deduplicated list of 
# candidate regular expression patterns.
#
# Core scenarios tested:
# A. Happy Path:
#    - Verifying pattern suggestion output for typical flags like 'SKY-1111-000'
#      and 'CTF{easy_flag_123}'.
#    - Verifying order and counts of specific vs. general patterns.
#
# B. Boundary Conditions:
#    - Handling single character inputs (e.g. 'A', '1', '{').
#    - Handling strings containing only delimiter/special characters (e.g. '---').
#    - Handling inputs with no numeric values or no alphabetic values.
#
# C. Edge Cases:
#    - Mixing case strings (e.g., 'AbCdEf') and verifying case-insensitive
#      or case-specific group behavior.
#
# D. Error Handling:
#    - Empty strings or strings containing only whitespace characters should 
#      raise ValueError.
# =====================================================================

# =====================================================================
# 2. Mocking/Setup Requirements
# =====================================================================
# - No external database, network APIs, or filesystem mocks are needed 
#   as `suggest_patterns` is a pure string-processing utility.
# =====================================================================

def test_suggest_patterns_happy_path_sky():
    """
    Verifies that the suggestions for a hyphenated alpha-numeric flag like 'SKY-1111-000'
    include specific character group counts, variable length matches, and the literal match.
    Both unanchored and anchored options are verified.
    """
    patterns = suggest_patterns("SKY-1111-000")
    
    # Asserting we get a list of patterns
    assert isinstance(patterns, list)
    assert len(patterns) > 0
    
    # Expected unanchored options:
    assert "[A-Z]{3}-\\d{4}-\\d{3}" in patterns
    assert "[A-Z]+-\\d+-\\d+" in patterns
    assert "[A-Za-z]{3}-\\d{4}-\\d{3}" in patterns
    assert "[A-Za-z0-9\\-]+" in patterns
    assert "SKY-1111-000" in patterns
    
    # Expected anchored options:
    assert "^[A-Z]{3}-\\d{4}-\\d{3}$" in patterns
    assert "^[A-Z]+-\\d+-\\d+$" in patterns
    assert "^SKY-1111-000$" in patterns

def test_suggest_patterns_happy_path_ctf():
    """
    Verifies suggestions for flags with braces and underscores like 'CTF{easy_flag_123}'.
    Note that special regex characters like '{' and '}' are correctly escaped.
    """
    patterns = suggest_patterns("CTF{easy_flag_123}")
    
    # Unanchored options:
    assert "[A-Z]{3}\\{[a-z]{4}_[a-z]{4}_\\d{3}\\}" in patterns
    assert "[A-Z]+\\{[a-z]+_[a-z]+_\\d+\\}" in patterns
    assert "[A-Za-z0-9_\\{\\}]+" in patterns
    assert "CTF\\{easy_flag_123\\}" in patterns
    
    # Anchored options:
    assert "^[A-Z]{3}\\{[a-z]{4}_[a-z]{4}_\\d{3}\\}$" in patterns
    assert "^[A-Z]+\\{[a-z]+_[a-z]+_\\d+\\}$" in patterns
    assert "^CTF\\{easy_flag_123\\}$" in patterns


def test_suggest_patterns_only_specials():
    """
    Verifies that a string with only special characters works and generates valid patterns.
    """
    patterns = suggest_patterns("---")
    # All patterns should deduplicate to just the exact literal match or similar
    assert "^---$" in patterns

def test_suggest_patterns_single_char():
    """
    Verifies pattern suggestion on single character flags.
    """
    assert "^[A-Z]{1}$" in suggest_patterns("A")
    assert "^\\d{1}$" in suggest_patterns("5")

def test_suggest_patterns_empty_and_whitespace():
    """
    Verifies that empty string or whitespace-only inputs trigger a ValueError.
    """
    with pytest.raises(ValueError, match="Input string cannot be empty or whitespace only."):
        suggest_patterns("")
        
    with pytest.raises(ValueError, match="Input string cannot be empty or whitespace only."):
        suggest_patterns("   ")

def test_suggest_patterns_with_competition_name_braced():
    """
    Verifies that when the competition name is matched in a braced flag,
    additional general wildcard patterns like 'CTF\\{.*\\}' and '^CTF\\{.*\\}$' are generated.
    """
    patterns = suggest_patterns("CTF{easy_flag_123}", comp_name="CTF")
    
    # Check that competition prefix is kept literal in specific/variable patterns (both unanchored & anchored)
    assert "CTF\\{[a-z]{4}_[a-z]{4}_\\d{3}\\}" in patterns
    assert "^CTF\\{[a-z]{4}_[a-z]{4}_\\d{3}\\}$" in patterns
    
    # Check that braced wildcard options are suggested (both unanchored & anchored)
    assert "CTF\\{.*\\}" in patterns
    assert "CTF\\{.*?\\}" in patterns
    assert "CTF\\{[^}]*\\}" in patterns
    assert "^CTF\\{.*\\}$" in patterns
    assert "^CTF\\{[A-Za-z0-9_\\-]+\\}$" in patterns
    assert "^CTF\\{[a-z0-9_]+\\}$" in patterns

def test_suggest_patterns_with_competition_name_non_braced():
    """
    Verifies that when the competition name is matched in a non-braced flag,
    suffix wildcards like 'SKY-.*' and '^SKY-.*$' are suggested.
    """
    patterns = suggest_patterns("SKY-1111-000", comp_name="SKY")
    
    assert "SKY-\\d{4}-\\d{3}" in patterns
    assert "^SKY-\\d{4}-\\d{3}$" in patterns
    assert "SKY-.*" in patterns
    assert "^SKY-.*$" in patterns

def test_suggest_patterns_with_competition_name_mismatch():
    """
    Verifies that if the competition name is not in the example flag,
    it falls back to standard regex suggestion matching.
    """
    patterns_mismatch = suggest_patterns("CTF{easy_flag_123}", comp_name="SKY")
    patterns_none = suggest_patterns("CTF{easy_flag_123}")
    
    assert patterns_mismatch == patterns_none

