from typing import List, Dict, Any
from .base_tests import BaseTestGenerator


class CharTestGenerator(BaseTestGenerator):
    """Generate test cases for character literals."""
    
    # Common escape sequences
    ESCAPE_SEQUENCES = {
        ("Newline", '\\\\n', '\n',),          # Newline
        ("Carriage return", '\\\\r', '\r',),  # Carriage return
        ("Tab", '\\\\t', '\t',),              # Tab
        ("Backslash", '\\\\\\\\', '\\',),     # Backslash
        ("Single quote", "\\\\'", "'",),      # Single quote
        ("Null character", '\\\\0', '\0',),   # Null character
    }
    
    # Unicode escape examples
    UNICODE_ESCAPES = {
        '\\u{41}': 'A',
        '\\u{1F600}': '😀',
        '\\u{2764}': '❤',
        '\\u{0041}': 'A',
        '\\u{03B1}': 'α',
        '\\u{4E2D}': '中',
    }
    
    def generate_basic_tests(self):
        """Generate basic character literal tests."""
        # Simple ASCII letters
        self.make_success_test("Char Simple Letter Uppercase A", "'A'", "char", 'A')
        self.make_success_test("Char Simple Letter Lowercase a", "'a'", "char", 'a')
        self.make_success_test("Char Simple Letter Uppercase Z", "'Z'", "char", 'Z')
        self.make_success_test("Char Simple Letter Lowercase z", "'z'", "char", 'z')
        
        # Digits
        self.make_success_test("Char Digit 0", "'0'", "char", '0')
        self.make_success_test("Char Digit 5", "'5'", "char", '5')
        self.make_success_test("Char Digit 9", "'9'", "char", '9')
        
        # Special characters
        self.make_success_test("Char Space", "' '", "char", ' ')
        self.make_success_test("Char Exclamation", "'!'", "char", '!')
        self.make_success_test("Char Question Mark", "'?'", "char", '?')
        self.make_success_test("Char Period", "'.'", "char", '.')
        self.make_success_test("Char Comma", "','", "char", ',')
        self.make_success_test("Char Semicolon", "';'", "char", ';')
        self.make_success_test("Char Colon", "':'", "char", ':')
        
        # Operators and symbols
        self.make_success_test("Char Plus", "'+'", "char", '+')
        self.make_success_test("Char Minus", "'-'", "char", '-')
        self.make_success_test("Char Asterisk", "'*'", "char", '*')
        self.make_success_test("Char Slash", "'/'", "char", '/')
        self.make_success_test("Char Equals", "'='", "char", '=')
        self.make_success_test("Char Less Than", "'<'", "char", '<')
        self.make_success_test("Char Greater Than", "'>'", "char", '>')
        
        # Brackets and braces
        self.make_success_test("Char Left Paren", "'('", "char", '(')
        self.make_success_test("Char Right Paren", "')'", "char", ')')
        self.make_success_test("Char Left Bracket", "'['", "char", '[')
        self.make_success_test("Char Right Bracket", "']'", "char", ']')
        self.make_success_test("Char Left Brace", "'{'", "char", '{')
        self.make_success_test("Char Right Brace", "'}'", "char", '}')
    
    def generate_escape_sequence_tests(self):
        """Generate tests for escape sequences."""
        # Standard escape sequences
        for escape_name, escape_str, char_val in self.ESCAPE_SEQUENCES:
            name = f"Char Escape {escape_name}"
            code = f"'{escape_str}'"
            self.make_success_test(name, code, "char", char_val)
    
    def generate_hexadecimal_escape_tests(self):
        """Generate tests for hexadecimal escape sequences."""
        if self.ENABLE_CHAR_HEX_ESCAPE:
            # Additional specific hex escapes
            self.make_success_test("Char Hex Lowercase A", "'\\\\x61'", "char", 'a')
            self.make_success_test("Char Hex Uppercase A", "'\\\\x41'", "char", 'A')
            self.make_success_test("Char Hex Space", "'\\\\x20'", "char", ' ')
            self.make_success_test("Char Hex Tab", "'\\\\x09'", "char", '\t')
            self.make_success_test("Char Hex Newline", "'\\\\x0A'", "char", '\n')
            self.make_success_test("Char Hex Max ASCII", "'\\\\x7F'", "char", '\x7F')
    
    def generate_unicode_escape_tests(self):
        """Generate tests for Unicode escape sequences."""
        for escape_str, char_val in self.UNICODE_ESCAPES.items():
            name = f"Char Unicode {escape_str}"
            code = f"'{escape_str}'"
            self.make_success_test(name, code, "char", char_val)
        
        # Additional Unicode tests
        self.make_success_test("Char Unicode Smiley", "'\\u{1F600}'", "char", '😀')
        self.make_success_test("Char Unicode Heart", "'\\u{2764}'", "char", '❤')
        self.make_success_test("Char Unicode Star", "'\\u{2B50}'", "char", '⭐')
        self.make_success_test("Char Unicode Greek Alpha", "'\\u{03B1}'", "char", 'α')
        self.make_success_test("Char Unicode Greek Beta", "'\\u{03B2}'", "char", 'β')
        self.make_success_test("Char Unicode Chinese", "'\\u{4E2D}'", "char", '中')
        self.make_success_test("Char Unicode Arabic", "'\\u{0639}'", "char", 'ع')
        self.make_success_test("Char Unicode Cyrillic", "'\\u{0410}'", "char", 'А')
    
    def generate_unicode_direct_tests(self):
        """Generate tests for direct Unicode characters."""
        # Emoji
        self.make_success_test("Char Direct Emoji Smiley", "'😀'", "char", '😀')
        self.make_success_test("Char Direct Emoji Heart", "'❤'", "char", '❤')
        self.make_success_test("Char Direct Emoji Star", "'⭐'", "char", '⭐')
        self.make_success_test("Char Direct Emoji Thumbs Up", "'👍'", "char", '👍')
        
        # Greek letters
        self.make_success_test("Char Direct Greek Alpha", "'α'", "char", 'α')
        self.make_success_test("Char Direct Greek Beta", "'β'", "char", 'β')
        self.make_success_test("Char Direct Greek Pi", "'π'", "char", 'π')
        self.make_success_test("Char Direct Greek Omega", "'Ω'", "char", 'Ω')
        
        # Chinese characters
        self.make_success_test("Char Direct Chinese Middle", "'中'", "char", '中')
        self.make_success_test("Char Direct Chinese Character", "'文'", "char", '文')
        
        # Arabic
        self.make_success_test("Char Direct Arabic Letter", "'ع'", "char", 'ع')
        
        # Cyrillic
        self.make_success_test("Char Direct Cyrillic A", "'А'", "char", 'А')
        self.make_success_test("Char Direct Cyrillic Ya", "'Я'", "char", 'Я')
        
        # Mathematical symbols
        self.make_success_test("Char Direct Infinity", "'∞'", "char", '∞')
        self.make_success_test("Char Direct Sum", "'∑'", "char", '∑')
        self.make_success_test("Char Direct Integral", "'∫'", "char", '∫')
    
    def generate_whitespace_tests(self):
        """Generate tests with whitespace around character literals."""
        self.make_success_test("Char With Leading Whitespace", "  'A'", "char", 'A')
        self.make_success_test("Char With Trailing Whitespace", "'A'  ", "char", 'A')
        self.make_success_test("Char With Both Whitespace", "  'A'  ", "char", 'A')
        self.make_success_test("Char Tab Before", "\\t'B'", "char", 'B')
        self.make_success_test("Char Newline Before", "\\n'C'", "char", 'C')
    
    def generate_error_tests(self):
        """Generate error test cases."""
        # Empty character literal
        self.make_error_test("Char Empty Literal",
                           "''",
                           "Invalid character literal: empty character literal.")
        
        # Multiple characters (no escape)
        self.make_error_test("Char Multiple Characters",
                           "'AB'",
                           "Invalid character literal: unexpected 'B' in character.")
        
        # Unclosed quote
        self.make_error_test("Char Unclosed Quote",
                           "'A",
                           "Invalid character literal: unclosed character literal.")
        
        # Unescaped newline
        self.make_error_test("Char Unescaped Newline",
                           "'\\n'",
                           "Invalid character literal: unclosed character literal.")
        
        # Invalid escape sequence
        self.make_error_test("Char Invalid Escape",
                           "'\\\\q'",
                           "Invalid character literal: unknown escape sequence '\\\\q'.")
        
        # Invalid hex escape (not 2 digits)
        if self.ENABLE_CHAR_HEX_ESCAPE:
            self.make_error_test("Char Hex Escape Too Short",
                            "'\\\\x4'",
                            "Invalid character literal: hexadecimal escape must have exactly 2 digits.")
            
            self.make_error_test("Char Hex Escape Too Long",
                            "'\\\\x414'",
                            "Invalid character literal: hexadecimal escape must have exactly 2 digits.")
            
            # Invalid hex digits
            self.make_error_test("Char Hex Invalid Digit",
                            "'\\\\xGG'",
                            "Invalid character literal: invalid hexadecimal digit 'G'.")
        
        if self.ENABLE_UNICODE:
            # Invalid Unicode escape (no braces)
            self.make_error_test("Char Unicode No Braces",
                            "'\\u1F600'",
                            "Invalid character literal: Unicode escape must use braces \\u{...}.")
            
            # Invalid Unicode escape (empty)
            self.make_error_test("Char Unicode Empty",
                            "'\\u{}'",
                            "Invalid character literal: empty Unicode escape sequence.")
            
            # Invalid Unicode escape (too many digits)
            self.make_error_test("Char Unicode Too Many Digits",
                            "'\\u{1234567}'",
                            "Invalid character literal: Unicode escape sequence too long (max 6 hex digits).")
            
            # Invalid Unicode escape (invalid code point)
            self.make_error_test("Char Unicode Invalid Code Point",
                            "'\\u{D800}'",
                            "Invalid character literal: invalid Unicode code point (surrogate range).")
            
            self.make_error_test("Char Unicode Out Of Range",
                            "'\\u{110000}'",
                            "Invalid character literal: Unicode code point out of range (max 0x10FFFF).")
            
            # Invalid Unicode escape (non-hex digits)
            self.make_error_test("Char Unicode Invalid Hex",
                            "'\\u{GGGG}'",
                            "Invalid character literal: invalid hexadecimal digit 'G' in Unicode escape.")
            
            # Unclosed Unicode escape
            self.make_error_test("Char Unicode Unclosed",
                            "'\\u{1F600'",
                            "Invalid character literal: unclosed Unicode escape sequence.")
    
    def generate_edge_case_tests(self):
        """Generate edge case tests."""
        if self.ENABLE_CHAR_HEX_ESCAPE:
            # ASCII control characters
            self.make_success_test("Char ASCII Control SOH", "'\\\\x01'", "char", '\x01')
            self.make_success_test("Char ASCII Control BEL", "'\\\\x07'", "char", '\x07')
            self.make_success_test("Char ASCII Control ESC", "'\\\\x1B'", "char", '\x1B')
            self.make_success_test("Char ASCII Control DEL", "'\\\\x7F'", "char", '\x7F')
            
            # Extended ASCII
            self.make_success_test("Char Extended ASCII Lower", "'\\\\x80'", "char", '\x80')
            self.make_success_test("Char Extended ASCII Upper", "'\\\\xFF'", "char", '\xFF')
        
        if self.ENABLE_UNICODE:
            # Zero-width characters
            self.make_success_test("Char Zero Width Space", "'\\u{200B}'", "char", '\u200B')
            self.make_success_test("Char Zero Width Joiner", "'\\u{200D}'", "char", '\u200D')
            
            # Right-to-left marks
            self.make_success_test("Char RTL Mark", "'\\u{200F}'", "char", '\u200F')
            
            # Combining characters
            self.make_success_test("Char Combining Acute", "'\\u{0301}'", "char", '\u0301')
            
            # Low Unicode values
            self.make_success_test("Char Unicode Zero", "'\\u{0}'", "char", '\0')
            self.make_success_test("Char Unicode One", "'\\u{1}'", "char", '\x01')
            
            # High Unicode values (but valid)
            self.make_success_test("Char Unicode High Valid", "'\\u{10FFFF}'", "char", '\U0010FFFF')
    
    def generate_case_sensitivity_tests(self):
        """Generate tests for case sensitivity in escape sequences."""
        if self.ENABLE_CHAR_HEX_ESCAPE:
            # Hex escapes - lowercase x
            self.make_success_test("Char Hex Lowercase x", "'\\\\x41'", "char", 'A')
            
            # Hex digits - both cases
            self.make_success_test("Char Hex Digits Uppercase", "'\\\\xFF'", "char", '\xFF')
            self.make_success_test("Char Hex Digits Lowercase", "'\\\\xff'", "char", '\xff')
            self.make_success_test("Char Hex Digits Mixed", "'\\\\xAb'", "char", '\xAB')
        
        if self.ENABLE_UNICODE:
            # Unicode escapes - lowercase u
            self.make_success_test("Char Unicode Lowercase u", "'\\u{41}'", "char", 'A')
            
            # Unicode hex digits - both cases
            self.make_success_test("Char Unicode Hex Uppercase", "'\\u{1F600}'", "char", '😀')
            self.make_success_test("Char Unicode Hex Lowercase", "'\\u{1f600}'", "char", '😀')
            self.make_success_test("Char Unicode Hex Mixed", "'\\u{1F60a}'", "char", '😊')
    
    def generate_all_tests(self) -> List[Dict[str, Any]]:
        """Generate all character literal test cases."""
        # Basic tests
        self.generate_basic_tests()
        
        # Escape sequences
        self.generate_escape_sequence_tests()
        
        # Hexadecimal escapes
        self.generate_hexadecimal_escape_tests()
        
        if self.ENABLE_UNICODE:
            # Unicode escapes
            self.generate_unicode_escape_tests()
            
            # Direct Unicode characters
            self.generate_unicode_direct_tests()
        
        # Whitespace handling
        self.generate_whitespace_tests()
        
        # Error cases
        self.generate_error_tests()
        
        # Edge cases
        self.generate_edge_case_tests()
        
        # Case sensitivity
        self.generate_case_sensitivity_tests()
        
        return self.get_tests()
