# Validation 1:


// Demo form data with different validation rules
struct ValidationDemoData {
    fields: Vec<(String, String)>,
}

impl ValidationDemoData {
    fn new() -> Self {
        Self {
            fields: vec![
                ("👤 Name (max 20)".to_string(), "".to_string()),
                ("📧 Email (max 50, warn@40)".to_string(), "".to_string()),
                ("🔑 Password (5-20 chars)".to_string(), "".to_string()),
                ("🔢 ID (min 3, max 10)".to_string(), "".to_string()),
                ("📝 Comment (min 10, max 100)".to_string(), "".to_string()),
                ("🏷️  Tag (max 30, bytes)".to_string(), "".to_string()),
                ("🌍 Unicode (width, min 2)".to_string(), "".to_string()),
            ],
        }
    }
}

impl DataProvider for ValidationDemoData {
    fn field_count(&self) -> usize {
        self.fields.len()
    }

    fn field_name(&self, index: usize) -> &str {
        &self.fields[index].0
    }

    fn field_value(&self, index: usize) -> &str {
        &self.fields[index].1
    }

    fn set_field_value(&mut self, index: usize, value: String) {
        self.fields[index].1 = value;
    }

    fn supports_suggestions(&self, _field_index: usize) -> bool {
        false
    }

    fn display_value(&self, _index: usize) -> Option<&str> {
        None
    }

    // 🎯 NEW: Validation configuration per field
    fn validation_config(&self, field_index: usize) -> Option<ValidationConfig> {
        match field_index {
            0 => Some(ValidationConfig::with_max_length(20)), // Name: simple 20 char limit
            1 => Some(
                ValidationConfigBuilder::new()
                    .with_character_limits(
                        CharacterLimits::new(50).with_warning_threshold(40)
                    )
                    .build()
            ), // Email: 50 chars with warning at 40
            2 => Some(
                ValidationConfigBuilder::new()
                    .with_character_limits(CharacterLimits::new_range(5, 20))
                    .build()
            ), // Password: must be 5-20 characters (blocks field switching if 1-4 chars)
            3 => Some(
                ValidationConfigBuilder::new()
                    .with_character_limits(CharacterLimits::new_range(3, 10))
                    .build()
            ), // ID: must be 3-10 characters (blocks field switching if 1-2 chars)
            4 => Some(
                ValidationConfigBuilder::new()
                    .with_character_limits(CharacterLimits::new_range(10, 100))
                    .build()
            ), // Comment: must be 10-100 characters (blocks field switching if 1-9 chars)
            5 => Some(
                ValidationConfigBuilder::new()
                    .with_character_limits(
                        CharacterLimits::new(30).with_count_mode(CountMode::Bytes)
                    )
                    .build()
            ), // Tag: 30 bytes (useful for UTF-8)
            6 => Some(
                ValidationConfigBuilder::new()
                    .with_character_limits(
                        CharacterLimits::new_range(2, 20).with_count_mode(CountMode::DisplayWidth)
                    )
                    .build()
            ), // Unicode: 2-20 display width (useful for CJK characters, blocks if 1 char)
            _ => None,
        }
    }
}

# Validation2:

// Advanced demo form with creative and edge-case-heavy validation patterns
struct AdvancedPatternData {
    fields: Vec<(String, String)>,
}

impl AdvancedPatternData {
    fn new() -> Self {
        Self {
            fields: vec![
                ("🕐 Time (HH:MM) - 24hr format".to_string(), "".to_string()),
                ("🎨 Hex Color (#RRGGBB) - Web colors".to_string(), "".to_string()),
                ("🌐 IPv4 (XXX.XXX.XXX.XXX) - Network address".to_string(), "".to_string()),
                ("🏷️  Product Code (ABC-123-XYZ) - Mixed format".to_string(), "".to_string()),
                ("📅 Date Code (2024W15) - Year + Week".to_string(), "".to_string()),
                ("🔢 Binary (101010) - Only 0s and 1s".to_string(), "".to_string()),
                ("🎯 Complex ID (A1-B2C-3D4E) - Multi-rule".to_string(), "".to_string()),
                ("🚀 Custom Pattern - Advanced logic".to_string(), "".to_string()),
            ],
        }
    }
}

impl DataProvider for AdvancedPatternData {
    fn field_count(&self) -> usize { self.fields.len() }
    fn field_name(&self, index: usize) -> &str { &self.fields[index].0 }
    fn field_value(&self, index: usize) -> &str { &self.fields[index].1 }
    fn set_field_value(&mut self, index: usize, value: String) { self.fields[index].1 = value; }

    fn validation_config(&self, field_index: usize) -> Option<ValidationConfig> {
        match field_index {
            0 => {
                // 🕐 Time (HH:MM) - Hours 00-23, Minutes 00-59
                // This showcases: Multiple position ranges, exact character matching, custom validation
                let time_pattern = PatternFilters::new()
                    .add_filter(PositionFilter::new(
                        PositionRange::Multiple(vec![0, 1, 3, 4]), // Hours and minutes positions
                        CharacterFilter::Numeric,
                    ))
                    .add_filter(PositionFilter::new(
                        PositionRange::Single(2), // Colon separator
                        CharacterFilter::Exact(':'),
                    ));

                Some(ValidationConfigBuilder::new()
                    .with_pattern_filters(time_pattern)
                    .with_max_length(5) // HH:MM = 5 characters
                    .build())
            }
            1 => {
                // 🎨 Hex Color (#RRGGBB) - Web color format
                // This showcases: OneOf filter with hex digits, exact character at start
                let hex_digits = vec!['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','a','b','c','d','e','f'];
                let hex_color_pattern = PatternFilters::new()
                    .add_filter(PositionFilter::new(
                        PositionRange::Single(0), // Hash symbol
                        CharacterFilter::Exact('#'),
                    ))
                    .add_filter(PositionFilter::new(
                        PositionRange::Range(1, 6), // 6 hex digits for RGB
                        CharacterFilter::OneOf(hex_digits),
                    ));

                Some(ValidationConfigBuilder::new()
                    .with_pattern_filters(hex_color_pattern)
                    .with_max_length(7) // #RRGGBB = 7 characters
                    .build())
            }
            2 => {
                // 🌐 IPv4 Address (XXX.XXX.XXX.XXX) - Network address
                // This showcases: Complex pattern with dots at specific positions
                let ipv4_pattern = PatternFilters::new()
                    .add_filter(PositionFilter::new(
                        PositionRange::Multiple(vec![3, 7, 11]), // Dots at specific positions
                        CharacterFilter::Exact('.'),
                    ))
                    .add_filter(PositionFilter::new(
                        PositionRange::Multiple(vec![0,1,2,4,5,6,8,9,10,12,13,14]), // Number positions
                        CharacterFilter::Numeric,
                    ));

                Some(ValidationConfigBuilder::new()
                    .with_pattern_filters(ipv4_pattern)
                    .with_max_length(15) // XXX.XXX.XXX.XXX = up to 15 chars
                    .build())
            }
            3 => {
                // 🏷️ Product Code (ABC-123-XYZ) - Mixed format sections
                // This showcases: Different rules for different sections
                let product_code_pattern = PatternFilters::new()
                    .add_filter(PositionFilter::new(
                        PositionRange::Range(0, 2), // First 3 positions: letters
                        CharacterFilter::Alphabetic,
                    ))
                    .add_filter(PositionFilter::new(
                        PositionRange::Multiple(vec![3, 7]), // Dashes
                        CharacterFilter::Exact('-'),
                    ))
                    .add_filter(PositionFilter::new(
                        PositionRange::Range(4, 6), // Middle 3 positions: numbers
                        CharacterFilter::Numeric,
                    ))
                    .add_filter(PositionFilter::new(
                        PositionRange::Range(8, 10), // Last 3 positions: letters
                        CharacterFilter::Alphabetic,
                    ));

                Some(ValidationConfigBuilder::new()
                    .with_pattern_filters(product_code_pattern)
                    .with_max_length(11) // ABC-123-XYZ = 11 characters
                    .build())
            }
            4 => {
                // 📅 Date Code (2024W15) - Year + Week format
                // This showcases: From position filtering and mixed patterns
                let date_code_pattern = PatternFilters::new()
                    .add_filter(PositionFilter::new(
                        PositionRange::Range(0, 3), // Year: 4 digits
                        CharacterFilter::Numeric,
                    ))
                    .add_filter(PositionFilter::new(
                        PositionRange::Single(4), // Week indicator
                        CharacterFilter::Exact('W'),
                    ))
                    .add_filter(PositionFilter::new(
                        PositionRange::From(5), // Week number: rest are digits
                        CharacterFilter::Numeric,
                    ));

                Some(ValidationConfigBuilder::new()
                    .with_pattern_filters(date_code_pattern)
                    .with_max_length(7) // 2024W15 = 7 characters
                    .build())
            }
            5 => {
                // 🔢 Binary (101010) - Only 0s and 1s
                // This showcases: OneOf filter with limited character set
                let binary_pattern = PatternFilters::new()
                    .add_filter(PositionFilter::new(
                        PositionRange::From(0), // All positions
                        CharacterFilter::OneOf(vec!['0', '1']),
                    ));

                Some(ValidationConfigBuilder::new()
                    .with_pattern_filters(binary_pattern)
                    .with_max_length(16) // Allow up to 16 binary digits
                    .build())
            }
            6 => {
                // 🎯 Complex ID (A1-B2C-3D4E) - Multiple overlapping rules
                // This showcases: Complex overlapping patterns and edge cases
                let complex_id_pattern = PatternFilters::new()
                    .add_filter(PositionFilter::new(
                        PositionRange::Multiple(vec![0, 3, 6, 8]), // Letter positions
                        CharacterFilter::Alphabetic,
                    ))
                    .add_filter(PositionFilter::new(
                        PositionRange::Multiple(vec![1, 4, 7, 9]), // Number positions
                        CharacterFilter::Numeric,
                    ))
                    .add_filter(PositionFilter::new(
                        PositionRange::Multiple(vec![2, 5]), // Dashes
                        CharacterFilter::Exact('-'),
                    ))
                    .add_filter(PositionFilter::new(
                        PositionRange::Single(5), // Special case: override dash with letter C
                        CharacterFilter::Alphabetic, // This creates an interesting edge case
                    ));

                Some(ValidationConfigBuilder::new()
                    .with_pattern_filters(complex_id_pattern)
                    .with_max_length(10) // A1-B2C-3D4E = 10 characters
                    .build())
            }
            7 => {
                // 🚀 Custom Pattern - Advanced logic with custom function
                // This showcases: Custom validation function for complex rules
                let custom_pattern = PatternFilters::new()
                    .add_filter(PositionFilter::new(
                        PositionRange::From(0),
                        CharacterFilter::Custom(Arc::new(|c| {
                            // Advanced rule: Alternating vowels and consonants!
                            // Even positions (0,2,4...): vowels (a,e,i,o,u)
                            // Odd positions (1,3,5...): consonants
                            let vowels = ['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U'];

                            // For demo purposes, we'll just accept alphabetic characters
                            // In real usage, you'd implement the alternating logic based on position
                            c.is_alphabetic()
                        })),
                    ));

                Some(ValidationConfigBuilder::new()
                    .with_pattern_filters(custom_pattern)
                    .with_max_length(12) // Allow up to 12 characters
                    .build())
            }
            _ => None,
        }
    }
}

Validation3:

// Demo data with comprehensive mask examples
struct MaskDemoData {
    fields: Vec<(String, String)>,
}

impl MaskDemoData {
    fn new() -> Self {
        Self {
            fields: vec![
                ("📞 Phone (Dynamic)".to_string(), "".to_string()),
                ("📞 Phone (Template)".to_string(), "".to_string()),
                ("📅 Date US (MM/DD/YYYY)".to_string(), "".to_string()),
                ("📅 Date EU (DD.MM.YYYY)".to_string(), "".to_string()),
                ("📅 Date ISO (YYYY-MM-DD)".to_string(), "".to_string()),
                ("🏛️ SSN (XXX-XX-XXXX)".to_string(), "".to_string()),
                ("💳 Credit Card".to_string(), "".to_string()),
                ("🏢 Employee ID (EMP-####)".to_string(), "".to_string()),
                ("📦 Product Code (ABC###XYZ)".to_string(), "".to_string()),
                ("🌈 Custom Separators".to_string(), "".to_string()),
                ("⭐ Custom Placeholders".to_string(), "".to_string()),
                ("🎯 Mixed Input Chars".to_string(), "".to_string()),
            ],
        }
    }
}

impl DataProvider for MaskDemoData {
    fn field_count(&self) -> usize { self.fields.len() }
    fn field_name(&self, index: usize) -> &str { &self.fields[index].0 }
    fn field_value(&self, index: usize) -> &str { &self.fields[index].1 }
    fn set_field_value(&mut self, index: usize, value: String) { self.fields[index].1 = value; }

    fn validation_config(&self, field_index: usize) -> Option<ValidationConfig> {
        match field_index {
            0 => {
                // 📞 Phone (Dynamic) - FIXED: Perfect mask/limit coordination
                let phone_mask = DisplayMask::new("(###) ###-####", '#');
                Some(ValidationConfigBuilder::new()
                    .with_display_mask(phone_mask)
                    .with_max_length(10)  // ✅ CRITICAL: Exactly matches 10 input positions
                    .build())
            }
            1 => {
                // 📞 Phone (Template) - FIXED: Perfect mask/limit coordination
                let phone_template = DisplayMask::new("(###) ###-####", '#')
                    .with_template('_');
                Some(ValidationConfigBuilder::new()
                    .with_display_mask(phone_template)
                    .with_max_length(10)  // ✅ CRITICAL: Exactly matches 10 input positions
                    .build())
            }
            2 => {
                // 📅 Date US (MM/DD/YYYY) - American date format
                let us_date = DisplayMask::new("##/##/####", '#');
                Some(ValidationConfig::with_mask(us_date))
            }
            3 => {
                // 📅 Date EU (DD.MM.YYYY) - European date format with dots
                let eu_date = DisplayMask::new("##.##.####", '#')
                    .with_template('•');
                Some(ValidationConfig::with_mask(eu_date))
            }
            4 => {
                // 📅 Date ISO (YYYY-MM-DD) - ISO date format
                let iso_date = DisplayMask::new("####-##-##", '#')
                    .with_template('-');
                Some(ValidationConfig::with_mask(iso_date))
            }
            5 => {
                // 🏛️ SSN using custom input character 'X' - FIXED: Perfect coordination
                let ssn_mask = DisplayMask::new("XXX-XX-XXXX", 'X');
                Some(ValidationConfigBuilder::new()
                    .with_display_mask(ssn_mask)
                    .with_max_length(9)  // ✅ CRITICAL: Exactly matches 9 input positions
                    .build())
            }
            6 => {
                // 💳 Credit Card (16 digits with spaces) - FIXED: Perfect coordination
                let cc_mask = DisplayMask::new("#### #### #### ####", '#')
                    .with_template('•');
                Some(ValidationConfigBuilder::new()
                    .with_display_mask(cc_mask)
                    .with_max_length(16)  // ✅ CRITICAL: Exactly matches 16 input positions
                    .build())
            }
            7 => {
                // 🏢 Employee ID with business prefix
                let emp_id = DisplayMask::new("EMP-####", '#');
                Some(ValidationConfig::with_mask(emp_id))
            }
            8 => {
                // 📦 Product Code with mixed letters and numbers
                let product_code = DisplayMask::new("ABC###XYZ", '#');
                Some(ValidationConfig::with_mask(product_code))
            }
            9 => {
                // 🌈 Custom Separators - Using | and ~ as separators
                let custom_sep = DisplayMask::new("##|##~####", '#')
                    .with_template('?');
                Some(ValidationConfig::with_mask(custom_sep))
            }
            10 => {
                // ⭐ Custom Placeholders - Using different placeholder characters
                let custom_placeholder = DisplayMask::new("##-##-##", '#')
                    .with_template('★');
                Some(ValidationConfig::with_mask(custom_placeholder))
            }
            11 => {
                // 🎯 Mixed Input Characters - Using 'N' for numbers
                let mixed_input = DisplayMask::new("ID:NNN-NNN", 'N');
                Some(ValidationConfig::with_mask(mixed_input))
            }
            _ => None,
        }
    }
}

Validation4:

/// PSC (Postal Code) Formatter: "01001" -> "010 01"
struct PSCFormatter;

impl CustomFormatter for PSCFormatter {
    fn format(&self, raw: &str) -> FormattingResult {
        if raw.is_empty() {
            return FormattingResult::success("");
        }

        // Validate: only digits allowed
        if !raw.chars().all(|c| c.is_ascii_digit()) {
            return FormattingResult::error("PSC must contain only digits");
        }

        let len = raw.chars().count();
        match len {
            0 => FormattingResult::success(""),
            1..=3 => FormattingResult::success(raw),
            4 => FormattingResult::warning(
                format!("{} ", &raw[..3]),
                "PSC incomplete (4/5 digits)"
            ),
            5 => {
                let formatted = format!("{} {}", &raw[..3], &raw[3..]);
                if raw == "00000" {
                    FormattingResult::warning(formatted, "Invalid PSC: 00000")
                } else {
                    FormattingResult::success(formatted)
                }
            },
            _ => FormattingResult::error("PSC too long (max 5 digits)"),
        }
    }
}

/// Phone Number Formatter: "1234567890" -> "(123) 456-7890"
struct PhoneFormatter;

impl CustomFormatter for PhoneFormatter {
    fn format(&self, raw: &str) -> FormattingResult {
        if raw.is_empty() {
            return FormattingResult::success("");
        }

        // Only digits allowed
        if !raw.chars().all(|c| c.is_ascii_digit()) {
            return FormattingResult::error("Phone must contain only digits");
        }

        let len = raw.chars().count();
        match len {
            0 => FormattingResult::success(""),
            1..=3 => FormattingResult::success(format!("({raw})")),
            4..=6 => FormattingResult::success(format!("({}) {}", &raw[..3], &raw[3..])),
            7..=10 => FormattingResult::success(format!("({}) {}-{}", &raw[..3], &raw[3..6], &raw[6..])),
            10 => {
                let formatted = format!("({}) {}-{}", &raw[..3], &raw[3..6], &raw[6..]);
                FormattingResult::success(formatted)
            },
            _ => FormattingResult::warning(
                format!("({}) {}-{}", &raw[..3], &raw[3..6], &raw[6..10]),
                "Phone too long (extra digits ignored)"
            ),
        }
    }
}

/// Credit Card Formatter: "1234567890123456" -> "1234 5678 9012 3456"
struct CreditCardFormatter;

impl CustomFormatter for CreditCardFormatter {
    fn format(&self, raw: &str) -> FormattingResult {
        if raw.is_empty() {
            return FormattingResult::success("");
        }

        if !raw.chars().all(|c| c.is_ascii_digit()) {
            return FormattingResult::error("Card number must contain only digits");
        }

        let mut formatted = String::new();
        for (i, ch) in raw.chars().enumerate() {
            if i > 0 && i % 4 == 0 {
                formatted.push(' ');
            }
            formatted.push(ch);
        }

        let len = raw.chars().count();
        match len {
            0..=15 => FormattingResult::warning(formatted, format!("Card incomplete ({len}/16 digits)")),
            16 => FormattingResult::success(formatted),
            _ => FormattingResult::warning(formatted, "Card too long (extra digits shown)"),
        }
    }
}






/// Date Formatter: "12012024" -> "12/01/2024"
struct DateFormatter;

impl CustomFormatter for DateFormatter {
    fn format(&self, raw: &str) -> FormattingResult {
        if raw.is_empty() {
            return FormattingResult::success("");
        }

        if !raw.chars().all(|c| c.is_ascii_digit()) {
            return FormattingResult::error("Date must contain only digits");
        }

        let len = raw.len();
        match len {
            0 => FormattingResult::success(""),
            1..=2 => FormattingResult::success(raw.to_string()),
            3..=4 => FormattingResult::success(format!("{}/{}", &raw[..2], &raw[2..])),
            5..=8 => FormattingResult::success(format!("{}/{}/{}", &raw[..2], &raw[2..4], &raw[4..])),
            8 => {
                let month = &raw[..2];
                let day = &raw[2..4];
                let year = &raw[4..];

                // Basic validation
                let m: u32 = month.parse().unwrap_or(0);
                let d: u32 = day.parse().unwrap_or(0);

                if m == 0 || m > 12 {
                    FormattingResult::warning(
                        format!("{month}/{day}/{year}"),
                        "Invalid month (01-12)"
                    )
                } else if d == 0 || d > 31 {
                    FormattingResult::warning(
                        format!("{month}/{day}/{year}"),
                        "Invalid day (01-31)"
                    )
                } else {
                    FormattingResult::success(format!("{month}/{day}/{year}"))
                }
            },
            _ => FormattingResult::error("Date too long (MMDDYYYY format)"),
        }
    }
}

// Enhanced demo data with multiple formatter types
struct MultiFormatterDemoData {
    fields: Vec<(String, String)>,
}

impl MultiFormatterDemoData {
    fn new() -> Self {
        Self {
            fields: vec![
                ("🏁 PSC (01001)".to_string(), "".to_string()),
                ("📞 Phone (1234567890)".to_string(), "".to_string()),
                ("💳 Credit Card (16 digits)".to_string(), "".to_string()),
                ("📅 Date (12012024)".to_string(), "".to_string()),
                ("📝 Plain Text".to_string(), "".to_string()),
            ],
        }
    }
}

impl DataProvider for MultiFormatterDemoData {
    fn field_count(&self) -> usize {
        self.fields.len()
    }

    fn field_name(&self, index: usize) -> &str {
        &self.fields[index].0
    }

    fn field_value(&self, index: usize) -> &str {
        &self.fields[index].1
    }

    fn set_field_value(&mut self, index: usize, value: String) {
        self.fields[index].1 = value;
    }

    #[cfg(feature = "validation")]
    fn validation_config(&self, field_index: usize) -> Option<ValidationConfig> {
        match field_index {
            0 => Some(ValidationConfigBuilder::new()
                .with_custom_formatter(Arc::new(PSCFormatter))
                .with_max_length(5)
                .build()),
            1 => Some(ValidationConfigBuilder::new()
                .with_custom_formatter(Arc::new(PhoneFormatter))
                .with_max_length(12)
                .build()),
            2 => Some(ValidationConfigBuilder::new()
                .with_custom_formatter(Arc::new(CreditCardFormatter))
                .with_max_length(20)
                .build()),
            3 => Some(ValidationConfigBuilder::new()
                .with_custom_formatter(Arc::new(DateFormatter))
                .with_max_length(8)
                .build()),
            4 => Some(ValidationConfigBuilder::new()
                .with_custom_formatter(Arc::new(DateFormatter))
                .with_max_length(8)
                .build()),
            _ => None, // Plain text field - no formatter
        }
    }
}


Validation5:


/// PSC Formatter with enhanced validation context
struct PSCFormatter;

impl CustomFormatter for PSCFormatter {
    fn format(&self, raw: &str) -> FormattingResult {
        if raw.is_empty() {
            return FormattingResult::success("");
        }

        if !raw.chars().all(|c| c.is_ascii_digit()) {
            return FormattingResult::error("PSC must contain only digits");
        }

        match raw.len() {
            0 => FormattingResult::success(""),
            1..=3 => FormattingResult::success(raw.to_string()),
            4 => FormattingResult::warning(
                format!("{} ", &raw[..3]),
                "PSC incomplete - external validation pending"
            ),
            5 => FormattingResult::success(format!("{} {}", &raw[..3], &raw[3..])),
            _ => FormattingResult::error("PSC too long (max 5 digits)"),
        }
    }
}

/// Credit Card Formatter for external validation demo
struct CreditCardFormatter;

impl CustomFormatter for CreditCardFormatter {
    fn format(&self, raw: &str) -> FormattingResult {
        if raw.is_empty() {
            return FormattingResult::success("");
        }

        if !raw.chars().all(|c| c.is_ascii_digit()) {
            return FormattingResult::error("Card number must contain only digits");
        }

        let mut formatted = String::new();
        for (i, ch) in raw.chars().enumerate() {
            if i > 0 && i % 4 == 0 {
                formatted.push(' ');
            }
            formatted.push(ch);
        }

        match raw.len() {
            0..=15 => FormattingResult::warning(formatted, "Card incomplete - validation pending"),
            16 => FormattingResult::success(formatted),
            _ => FormattingResult::warning(formatted, "Card too long - validation may fail"),
        }
    }
}

/// Comprehensive validation cache
struct ValidationCache {
    results: HashMap<String, ExternalValidationState>,
}

impl ValidationCache {
    fn new() -> Self {
        Self {
            results: HashMap::new(),
        }
    }

    fn get(&self, key: &str) -> Option<&ExternalValidationState> {
        self.results.get(key)
    }

    fn set(&mut self, key: String, result: ExternalValidationState) {
        self.results.insert(key, result);
    }

    fn clear(&mut self) {
        self.results.clear();
    }
}

/// Simulated external validation services
struct ValidationServices {
    cache: ValidationCache,
}

impl ValidationServices {
    fn new() -> Self {
        Self {
            cache: ValidationCache::new(),
        }
    }

    /// PSC validation: simulates postal service API lookup
    fn validate_psc(&mut self, psc: &str) -> ExternalValidationState {
        let cache_key = format!("psc:{psc}");
        if let Some(cached) = self.cache.get(&cache_key) {
            return cached.clone();
        }

        if psc.is_empty() {
            return ExternalValidationState::NotValidated;
        }

        if !psc.chars().all(|c| c.is_ascii_digit()) || psc.len() != 5 {
            let result = ExternalValidationState::Invalid {
                message: "Invalid PSC format".to_string(),
                suggestion: Some("Enter 5 digits".to_string())
            };
            self.cache.set(cache_key, result.clone());
            return result;
        }

        // Simulate realistic PSC validation scenarios
        let result = match psc {
            "00000" | "99999" => ExternalValidationState::Invalid {
                message: "PSC does not exist".to_string(),
                suggestion: Some("Check postal code".to_string())
            },
            "01001" => ExternalValidationState::Valid(Some("Prague 1 - verified".to_string())),
            "10000" => ExternalValidationState::Valid(Some("Bratislava - verified".to_string())),
            "12345" => ExternalValidationState::Warning {
                message: "PSC region deprecated - still valid".to_string()
            },
            "50000" => ExternalValidationState::Invalid {
                message: "PSC temporarily unavailable".to_string(),
                suggestion: Some("Try again later".to_string())
            },
            _ => {
                // Most PSCs are valid with generic info
                let region = match &psc[..2] {
                    "01" | "02" | "03" => "Prague region",
                    "10" | "11" | "12" => "Bratislava region",
                    "20" | "21" => "Brno region",
                    _ => "Valid postal region"
                };
                ExternalValidationState::Valid(Some(format!("{region} - verified")))
            }
        };

        self.cache.set(cache_key, result.clone());
        result
    }

    /// Email validation: simulates domain checking
    fn validate_email(&mut self, email: &str) -> ExternalValidationState {
        let cache_key = format!("email:{email}");
        if let Some(cached) = self.cache.get(&cache_key) {
            return cached.clone();
        }

        if email.is_empty() {
            return ExternalValidationState::NotValidated;
        }

        if !email.contains('@') {
            let result = ExternalValidationState::Invalid {
                message: "Email must contain @".to_string(),
                suggestion: Some("Format: user@domain.com".to_string())
            };
            self.cache.set(cache_key, result.clone());
            return result;
        }

        let parts: Vec<&str> = email.split('@').collect();
        if parts.len() != 2 || parts[0].is_empty() || parts[1].is_empty() {
            let result = ExternalValidationState::Invalid {
                message: "Invalid email format".to_string(),
                suggestion: Some("Format: user@domain.com".to_string())
            };
            self.cache.set(cache_key, result.clone());
            return result;
        }

        let domain = parts[1];
        let result = match domain {
            "gmail.com" | "outlook.com" | "yahoo.com" => {
                ExternalValidationState::Valid(Some("Popular email provider - verified".to_string()))
            },
            "example.com" | "test.com" => {
                ExternalValidationState::Warning {
                    message: "Test domain - email may not be deliverable".to_string()
                }
            },
            "blocked.com" | "spam.com" => {
                ExternalValidationState::Invalid {
                    message: "Domain blocked".to_string(),
                    suggestion: Some("Use different email provider".to_string())
                }
            },
            _ if domain.contains('.') => {
                ExternalValidationState::Valid(Some("Domain appears valid - not verified".to_string()))
            },
            _ => {
                ExternalValidationState::Invalid {
                    message: "Invalid domain format".to_string(),
                    suggestion: Some("Domain must contain '.'".to_string())
                }
            }
        };

        self.cache.set(cache_key, result.clone());
        result
    }

    /// Username validation: simulates availability checking
    fn validate_username(&mut self, username: &str) -> ExternalValidationState {
        let cache_key = format!("username:{username}");
        if let Some(cached) = self.cache.get(&cache_key) {
            return cached.clone();
        }

        if username.is_empty() {
            return ExternalValidationState::NotValidated;
        }

        if username.len() < 3 {
            let result = ExternalValidationState::Invalid {
                message: "Username too short".to_string(),
                suggestion: Some("Minimum 3 characters".to_string())
            };
            self.cache.set(cache_key, result.clone());
            return result;
        }

        if !username.chars().all(|c| c.is_alphanumeric() || c == '_') {
            let result = ExternalValidationState::Invalid {
                message: "Invalid characters".to_string(),
                suggestion: Some("Use letters, numbers, underscore only".to_string())
            };
            self.cache.set(cache_key, result.clone());
            return result;
        }

        let result = match username {
            "admin" | "root" | "user" | "test" => {
                ExternalValidationState::Invalid {
                    message: "Username reserved".to_string(),
                    suggestion: Some("Choose different username".to_string())
                }
            },
            "john123" | "alice_dev" => {
                ExternalValidationState::Invalid {
                    message: "Username already taken".to_string(),
                    suggestion: Some("Try variations or add numbers".to_string())
                }
            },
            username if username.starts_with("temp_") => {
                ExternalValidationState::Warning {
                    message: "Temporary username pattern - are you sure?".to_string()
                }
            },
            _ => {
                ExternalValidationState::Valid(Some("Username available - good choice!".to_string()))
            }
        };

        self.cache.set(cache_key, result.clone());
        result
    }

    /// API Key validation: simulates authentication service
    fn validate_api_key(&mut self, key: &str) -> ExternalValidationState {
        let cache_key = format!("apikey:{key}");
        if let Some(cached) = self.cache.get(&cache_key) {
            return cached.clone();
        }

        if key.is_empty() {
            return ExternalValidationState::NotValidated;
        }

        if key.len() < 20 {
            let result = ExternalValidationState::Invalid {
                message: "API key too short".to_string(),
                suggestion: Some("Valid keys are 32+ characters".to_string())
            };
            self.cache.set(cache_key, result.clone());
            return result;
        }

        let result = match key {
            "invalid_key_12345678901" => {
                ExternalValidationState::Invalid {
                    message: "API key not found".to_string(),
                    suggestion: Some("Check key and permissions".to_string())
                }
            },
            "expired_key_12345678901" => {
                ExternalValidationState::Invalid {
                    message: "API key expired".to_string(),
                    suggestion: Some("Generate new key".to_string())
                }
            },
            "limited_key_12345678901" => {
                ExternalValidationState::Warning {
                    message: "API key has limited permissions".to_string()
                }
            },
            key if key.starts_with("test_") => {
                ExternalValidationState::Warning {
                    message: "Test API key - limited functionality".to_string()
                }
            },
            _ if key.len() >= 32 => {
                ExternalValidationState::Valid(Some("API key authenticated - full access".to_string()))
            },
            _ => {
                ExternalValidationState::Invalid {
                    message: "Invalid API key format".to_string(),
                    suggestion: Some("Keys should be 32+ alphanumeric characters".to_string())
                }
            }
        };

        self.cache.set(cache_key, result.clone());
        result
    }

    /// Credit Card validation: simulates bank verification
    fn validate_credit_card(&mut self, card: &str) -> ExternalValidationState {
        let cache_key = format!("card:{card}");
        if let Some(cached) = self.cache.get(&cache_key) {
            return cached.clone();
        }

        if card.is_empty() {
            return ExternalValidationState::NotValidated;
        }

        if !card.chars().all(|c| c.is_ascii_digit()) || card.len() != 16 {
            let result = ExternalValidationState::Invalid {
                message: "Invalid card format".to_string(),
                suggestion: Some("Enter 16 digits".to_string())
            };
            self.cache.set(cache_key, result.clone());
            return result;
        }

        // Basic Luhn algorithm check (simplified)
        let sum: u32 = card.chars()
            .filter_map(|c| c.to_digit(10))
            .enumerate()
            .map(|(i, digit)| {
                if i % 2 == 0 {
                    let doubled = digit * 2;
                    if doubled > 9 { doubled - 9 } else { doubled }
                } else {
                    digit
                }
            })
            .sum();

        if sum % 10 != 0 {
            let result = ExternalValidationState::Invalid {
                message: "Invalid card number (failed checksum)".to_string(),
                suggestion: Some("Check card number".to_string())
            };
            self.cache.set(cache_key, result.clone());
            return result;
        }

        let result = match &card[..4] {
            "4000" => ExternalValidationState::Valid(Some("Visa - card verified".to_string())),
            "5555" => ExternalValidationState::Valid(Some("Mastercard - card verified".to_string())),
            "4111" => ExternalValidationState::Warning {
                message: "Test card number - not for real transactions".to_string()
            },
            "0000" => ExternalValidationState::Invalid {
                message: "Card declined by issuer".to_string(),
                suggestion: Some("Contact your bank".to_string())
            },
            _ => ExternalValidationState::Valid(Some("Card number valid - bank not verified".to_string()))
        };

        self.cache.set(cache_key, result.clone());
        result
    }

    fn clear_cache(&mut self) {
        self.cache.clear();
    }
}

/// Rich demo data with multiple validation types
struct ValidationDemoData {
    fields: Vec<(String, String)>,
}

impl ValidationDemoData {
    fn new() -> Self {
        Self {
            fields: vec![
                ("🏁 PSC (01001)".to_string(), "".to_string()),
                ("📧 Email (user@domain.com)".to_string(), "".to_string()),
                ("👤 Username (3+ chars)".to_string(), "".to_string()),
                ("🔑 API Key (32+ chars)".to_string(), "".to_string()),
                ("💳 Credit Card (16 digits)".to_string(), "".to_string()),
                ("📝 Notes (no validation)".to_string(), "".to_string()),
            ],
        }
    }
}

