// Extreme optimizations for base36 conversion
const BASE36_CHARS: &[u8; 36] = b"0123456789abcdefghijklmnopqrstuvwxyz";

// Lookup table for fast base36 to digit conversion
const BASE36_DECODE: [u8; 256] = {
    let mut table = [255u8; 256];
    let mut i = 0;
    while i < 10 {
        table[(b'0' + i) as usize] = i;
        i += 1;
    }
    let mut i = 0;
    while i < 26 {
        table[(b'a' + i) as usize] = i + 10;
        i += 1;
    }
    table
};

// Current optimized version (baseline)
#[inline(always)]
pub fn u64_to_base36_baseline(mut value: u64) -> String {
    if value == 0 {
        return "0".to_string();
    }
    
    let mut buffer: [u8; 13] = [0; 13];
    let mut pos = 13;

    while value > 0 {
        pos -= 1;
        buffer[pos] = BASE36_CHARS[(value % 36) as usize];
        value /= 36;
    }
    
    unsafe { String::from_utf8_unchecked(buffer[pos..].to_vec()) }
}

// Optimization 1: Aggressive loop unrolling for small values
#[inline(always)]
pub fn u64_to_base36_unrolled(mut value: u64) -> String {
    if value == 0 {
        return "0".to_string();
    }
    
    // Special cases for very common small values
    if value < 36 {
        return unsafe { String::from_utf8_unchecked(vec![BASE36_CHARS[value as usize]]) };
    }
    
    if value < 1296 { // 36^2
        let d1 = (value % 36) as usize;
        let d0 = (value / 36) as usize;
        return unsafe { String::from_utf8_unchecked(vec![BASE36_CHARS[d0], BASE36_CHARS[d1]]) };
    }
    
    if value < 46656 { // 36^3
        let d2 = (value % 36) as usize;
        value /= 36;
        let d1 = (value % 36) as usize;
        let d0 = (value / 36) as usize;
        return unsafe { String::from_utf8_unchecked(vec![BASE36_CHARS[d0], BASE36_CHARS[d1], BASE36_CHARS[d2]]) };
    }
    
    // General case with unrolled loop
    let mut buffer: [u8; 13] = [0; 13];
    let mut pos = 13;

    // Process multiple digits in each iteration when the number is large enough
    while value >= 1296 { // 36^2
        let chunk = (value % 1296) as usize;
        value /= 1296;
        
        pos -= 1;
        buffer[pos] = BASE36_CHARS[chunk % 36];
        pos -= 1;
        buffer[pos] = BASE36_CHARS[chunk / 36];
    }
    
    // Handle remaining digits
    while value > 0 {
        pos -= 1;
        buffer[pos] = BASE36_CHARS[(value % 36) as usize];
        value /= 36;
    }
    
    unsafe { String::from_utf8_unchecked(buffer[pos..].to_vec()) }
}

// Optimization 2: Strength reduction - replace division with multiplication
#[inline(always)]
pub fn u64_to_base36_strength_reduced(mut value: u64) -> String {
    if value == 0 {
        return "0".to_string();
    }
    
    let mut buffer: [u8; 13] = [0; 13];
    let mut pos = 13;

    // Use strength reduction: replace expensive division with shifts and subtracts
    while value > 0 {
        pos -= 1;
        // For base 36, we can optimize using the fact that 36 = 32 + 4 = 2^5 + 2^2
        // But since 36 is not a power of 2, regular division is actually efficient
        // due to compiler optimizations, so we keep it simple
        buffer[pos] = BASE36_CHARS[(value % 36) as usize];
        value /= 36;
    }
    
    unsafe { String::from_utf8_unchecked(buffer[pos..].to_vec()) }
}

// Optimization 3: Minimize branches with lookup tables
#[inline(always)]
pub fn u64_to_base36_branchless(mut value: u64) -> String {
    if value == 0 {
        return "0".to_string();
    }
    
    // Pre-compute strings for small values to avoid computation entirely
    static SMALL_VALUES: [&str; 36] = [
        "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
        "a", "b", "c", "d", "e", "f", "g", "h", "i", "j",
        "k", "l", "m", "n", "o", "p", "q", "r", "s", "t",
        "u", "v", "w", "x", "y", "z"
    ];
    
    if value < 36 {
        return SMALL_VALUES[value as usize].to_string();
    }
    
    let mut buffer: [u8; 13] = [0; 13];
    let mut pos = 13;

    while value > 0 {
        pos -= 1;
        buffer[pos] = BASE36_CHARS[(value % 36) as usize];
        value /= 36;
    }
    
    unsafe { String::from_utf8_unchecked(buffer[pos..].to_vec()) }
}

// Optimization 4: Template specialization for different ranges
#[inline(always)]
pub fn u64_to_base36_specialized(value: u64) -> String {
    match value {
        0 => "0".to_string(),
        1..=35 => unsafe { String::from_utf8_unchecked(vec![BASE36_CHARS[value as usize]]) },
        36..=1295 => {
            let d1 = (value % 36) as usize;
            let d0 = (value / 36) as usize;
            unsafe { String::from_utf8_unchecked(vec![BASE36_CHARS[d0], BASE36_CHARS[d1]]) }
        },
        1296..=46655 => {
            let mut v = value;
            let d2 = (v % 36) as usize;
            v /= 36;
            let d1 = (v % 36) as usize;
            let d0 = (v / 36) as usize;
            unsafe { String::from_utf8_unchecked(vec![BASE36_CHARS[d0], BASE36_CHARS[d1], BASE36_CHARS[d2]]) }
        },
        _ => u64_to_base36_baseline(value), // Fall back to general case
    }
}

// Parsing optimizations
#[inline(always)]
pub fn base36_to_u64_baseline(s: &str) -> Result<u64, String> {
    if s.is_empty() {
        return Err("Empty string".to_string());
    }
    
    let bytes = s.as_bytes();
    
    if bytes.len() == 1 {
        let digit = BASE36_DECODE[bytes[0] as usize];
        if digit == 255 {
            return Err(format!("Invalid character '{}' in base36 string", bytes[0] as char));
        }
        return Ok(digit as u64);
    }
    
    let mut result: u64 = 0;
    
    for &byte in bytes {
        let digit = BASE36_DECODE[byte as usize];
        if digit == 255 {
            return Err(format!("Invalid character '{}' in base36 string", byte as char));
        }
        
        result = match result.checked_mul(36).and_then(|r| r.checked_add(digit as u64)) {
            Some(val) => val,
            None => return Err("Overflow while parsing base36 string".to_string()),
        };
    }
    
    Ok(result)
}

// Optimization: Process multiple digits per iteration (Horner's method with batching)
#[inline(always)]
pub fn base36_to_u64_batched(s: &str) -> Result<u64, String> {
    if s.is_empty() {
        return Err("Empty string".to_string());
    }
    
    let bytes = s.as_bytes();
    let mut result: u64 = 0;
    let mut i = 0;
    
    // Process 2 digits at a time when possible (base^2 = 1296)
    while i + 1 < bytes.len() {
        let d0 = BASE36_DECODE[bytes[i] as usize];
        let d1 = BASE36_DECODE[bytes[i + 1] as usize];
        
        if d0 == 255 || d1 == 255 {
            return Err("Invalid character in base36 string".to_string());
        }
        
        // result = result * 36^2 + d0 * 36 + d1
        result = match result.checked_mul(1296).and_then(|r| r.checked_add((d0 as u64) * 36 + d1 as u64)) {
            Some(val) => val,
            None => return Err("Overflow while parsing base36 string".to_string()),
        };
        
        i += 2;
    }
    
    // Handle remaining single digit
    if i < bytes.len() {
        let digit = BASE36_DECODE[bytes[i] as usize];
        if digit == 255 {
            return Err("Invalid character in base36 string".to_string());
        }
        
        result = match result.checked_mul(36).and_then(|r| r.checked_add(digit as u64)) {
            Some(val) => val,
            None => return Err("Overflow while parsing base36 string".to_string()),
        };
    }
    
    Ok(result)
}

use std::time::Instant;

fn benchmark_all_versions() {
    println!("Running extreme base36 optimization benchmark...");
    println!("================================================");
    
    let iterations = 100;
    let test_ranges = [
        (0, 1000, 1),
        (1000, 1_000_000, 100),  
        (1_000_000, 1_000_000_000, 10_000),
    ];
    
    // Test encoding optimizations
    let encoding_funcs = [
        ("Baseline", u64_to_base36_baseline as fn(u64) -> String),
        ("Unrolled", u64_to_base36_unrolled),
        ("Strength Reduced", u64_to_base36_strength_reduced),
        ("Branchless", u64_to_base36_branchless),
        ("Specialized", u64_to_base36_specialized),
    ];
    
    for (name, func) in encoding_funcs {
        let start = Instant::now();
        
        for _ in 0..iterations {
            for (start_val, end_val, step) in test_ranges {
                for i in (start_val..=end_val).step_by(step) {
                    let encoded = func(i);
                    std::hint::black_box(encoded);
                }
            }
        }
        
        let elapsed = start.elapsed();
        println!("Encoding {:18}: {:?}", name, elapsed);
    }
    
    println!("\nTesting parsing optimizations...");
    
    // Generate test strings
    let mut test_strings = Vec::new();
    for (start_val, end_val, step) in test_ranges {
        for i in (start_val..=end_val).step_by(step) {
            test_strings.push(u64_to_base36_baseline(i));
        }
    }
    
    let parsing_funcs = [
        ("Baseline", base36_to_u64_baseline as fn(&str) -> Result<u64, String>),
        ("Batched", base36_to_u64_batched),
    ];
    
    for (name, func) in parsing_funcs {
        let start = Instant::now();
        
        for _ in 0..iterations {
            for s in &test_strings {
                let decoded = func(s).unwrap();
                std::hint::black_box(decoded);
            }
        }
        
        let elapsed = start.elapsed();
        println!("Parsing {:19}: {:?}", name, elapsed);
    }
}

fn main() {
    // Verify correctness first
    println!("Verifying correctness of all optimizations...");
    
    for i in 0..10000 {
        let reference = u64_to_base36_baseline(i);
        
        assert_eq!(u64_to_base36_unrolled(i), reference, "Unrolled failed at {}", i);
        assert_eq!(u64_to_base36_strength_reduced(i), reference, "Strength reduced failed at {}", i);
        assert_eq!(u64_to_base36_branchless(i), reference, "Branchless failed at {}", i);
        assert_eq!(u64_to_base36_specialized(i), reference, "Specialized failed at {}", i);
        
        // Test parsing too
        assert_eq!(base36_to_u64_batched(&reference).unwrap(), i, "Batched parsing failed at {}", i);
    }
    
    println!("✅ All optimizations verified for 10,000 values");
    println!();
    
    benchmark_all_versions();
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_u64_to_base36_baseline_specific_lines() {
        // Test lines 22-24 (value == 0 case)
        assert_eq!(u64_to_base36_baseline(0), "0");
        
        // Test lines 27-28 (buffer initialization and pos = 13)
        // Test lines 30-33 (while loop)
        assert_eq!(u64_to_base36_baseline(1), "1");
        assert_eq!(u64_to_base36_baseline(35), "z");
        assert_eq!(u64_to_base36_baseline(36), "10");
        assert_eq!(u64_to_base36_baseline(1296), "100");
        
        // Test line 36 (unsafe String::from_utf8_unchecked)
        assert_eq!(u64_to_base36_baseline(46656), "1000");
        assert_eq!(u64_to_base36_baseline(u64::MAX), "3w5e11264sgsf");
    }

    #[test]
    fn test_u64_to_base36_unrolled_specific_lines() {
        // Test lines 41-43 (value == 0 case)
        assert_eq!(u64_to_base36_unrolled(0), "0");
        
        // Test lines 47-48 (single digit case < 36)
        assert_eq!(u64_to_base36_unrolled(1), "1");
        assert_eq!(u64_to_base36_unrolled(35), "z");
        
        // Test lines 52-54 (two digit case < 1296)
        assert_eq!(u64_to_base36_unrolled(36), "10");
        assert_eq!(u64_to_base36_unrolled(1295), "zz");
        
        // Test lines 58-62 (three digit case < 46656)
        assert_eq!(u64_to_base36_unrolled(1296), "100");
        assert_eq!(u64_to_base36_unrolled(46655), "zzz");
        
        // Test lines 66-67 (general case buffer initialization)
        // Test lines 71-72 (unrolled while loop for >= 1296)
        assert_eq!(u64_to_base36_unrolled(46656), "1000");
        
        // Test lines 74-77 (chunk processing in unrolled loop)
        assert_eq!(u64_to_base36_unrolled(1679616), "10000"); // 36^4
        
        // Test lines 81-84 (remaining digits handling)
        assert_eq!(u64_to_base36_unrolled(60466176), "100000"); // 36^4 * 36
        
        // Test line 87 (unsafe String::from_utf8_unchecked)
        assert_eq!(u64_to_base36_unrolled(u64::MAX), "3w5e11264sgsf");
    }

    #[test]
    fn test_u64_to_base36_strength_reduced_specific_lines() {
        // Test lines 92-94 (value == 0 case)
        assert_eq!(u64_to_base36_strength_reduced(0), "0");
        
        // Test lines 97-98 (buffer initialization and pos = 13)
        // Test lines 101-102 (while loop)
        assert_eq!(u64_to_base36_strength_reduced(1), "1");
        assert_eq!(u64_to_base36_strength_reduced(35), "z");
        assert_eq!(u64_to_base36_strength_reduced(36), "10");
        
        // Test lines 106-107 (strength reduction logic)
        assert_eq!(u64_to_base36_strength_reduced(1296), "100");
        assert_eq!(u64_to_base36_strength_reduced(46656), "1000");
        
        // Test line 110 (unsafe String::from_utf8_unchecked)
        assert_eq!(u64_to_base36_strength_reduced(u64::MAX), "3w5e11264sgsf");
    }

    #[test]
    fn test_u64_to_base36_branchless_specific_lines() {
        // Test lines 115-117 (value == 0 case)
        assert_eq!(u64_to_base36_branchless(0), "0");
        
        // Test lines 121-125 (SMALL_VALUES static array definition and usage)
        assert_eq!(u64_to_base36_branchless(1), "1");
        assert_eq!(u64_to_base36_branchless(9), "9");
        assert_eq!(u64_to_base36_branchless(10), "a");
        assert_eq!(u64_to_base36_branchless(35), "z");
        
        // Test lines 128-129 (single digit case < 36)
        assert_eq!(u64_to_base36_branchless(25), "p");
        
        // Test lines 132-133 (buffer initialization)
        // Test lines 135-138 (while loop for larger values)
        assert_eq!(u64_to_base36_branchless(36), "10");
        assert_eq!(u64_to_base36_branchless(1296), "100");
        
        // Test line 141 (unsafe String::from_utf8_unchecked)
        assert_eq!(u64_to_base36_branchless(46656), "1000");
    }

    #[test]
    fn test_u64_to_base36_specialized_specific_lines() {
        // Test lines 146-153 (match arms for different ranges)
        assert_eq!(u64_to_base36_specialized(0), "0"); // 0 case
        assert_eq!(u64_to_base36_specialized(1), "1"); // 1..=35 case
        assert_eq!(u64_to_base36_specialized(35), "z"); // 1..=35 case
        assert_eq!(u64_to_base36_specialized(36), "10"); // 36..=1295 case
        assert_eq!(u64_to_base36_specialized(1295), "zz"); // 36..=1295 case
        
        // Test lines 155-161 (1296..=46655 case)
        assert_eq!(u64_to_base36_specialized(1296), "100");
        assert_eq!(u64_to_base36_specialized(46655), "zzz");
        
        // Test fallback to baseline (for values > 46655)
        assert_eq!(u64_to_base36_specialized(46656), u64_to_base36_baseline(46656));
        assert_eq!(u64_to_base36_specialized(u64::MAX), u64_to_base36_baseline(u64::MAX));
    }

    #[test]
    fn test_base36_to_u64_baseline_specific_lines() {
        // Test lines 169-171 (empty string case)
        match base36_to_u64_baseline("") {
            Err(msg) => assert_eq!(msg, "Empty string"),
            Ok(_) => panic!("Should have failed"),
        }
        
        // Test line 174 (get bytes)
        // Test lines 176-179 (single digit case)
        assert_eq!(base36_to_u64_baseline("0").unwrap(), 0);
        assert_eq!(base36_to_u64_baseline("9").unwrap(), 9);
        assert_eq!(base36_to_u64_baseline("a").unwrap(), 10);
        assert_eq!(base36_to_u64_baseline("z").unwrap(), 35);
        
        // Test invalid single character (lines 177-179)
        match base36_to_u64_baseline("@") {
            Err(msg) => assert!(msg.contains("Invalid character")),
            Ok(_) => panic!("Should have failed"),
        }
        
        // Test line 181 (return Ok(digit as u64))
        assert_eq!(base36_to_u64_baseline("1").unwrap(), 1);
        
        // Test line 184 (result initialization)
        // Test lines 186-189 (for loop with lookup table and invalid character)
        assert_eq!(base36_to_u64_baseline("10").unwrap(), 36);
        assert_eq!(base36_to_u64_baseline("zz").unwrap(), 1295);
        
        // Test invalid character in multi-digit string
        match base36_to_u64_baseline("a@b") {
            Err(msg) => assert!(msg.contains("Invalid character")),
            Ok(_) => panic!("Should have failed"),
        }
        
        // Test lines 192-194 (checked arithmetic and overflow)
        assert_eq!(base36_to_u64_baseline("abc").unwrap(), 13368);
        
        // Test overflow case
        let overflow_str = "zzzzzzzzzzzzzzzzzzzz";
        match base36_to_u64_baseline(overflow_str) {
            Err(msg) => assert_eq!(msg, "Overflow while parsing base36 string"),
            Ok(_) => panic!("Should have failed"),
        }
    }

    #[test]
    fn test_base36_to_u64_batched_specific_lines() {
        // Test basic functionality to cover the batched parsing logic
        assert_eq!(base36_to_u64_batched("0").unwrap(), 0);
        assert_eq!(base36_to_u64_batched("10").unwrap(), 36);
        assert_eq!(base36_to_u64_batched("100").unwrap(), 1296);
        assert_eq!(base36_to_u64_batched("abc").unwrap(), 13368);
        
        // Test error cases
        assert!(base36_to_u64_batched("").is_err());
        assert!(base36_to_u64_batched("@").is_err());
        assert!(base36_to_u64_batched("a@").is_err());
        
        // Test overflow
        let overflow_str = "zzzzzzzzzzzzzzzzzzzz";
        assert!(base36_to_u64_batched(overflow_str).is_err());
    }

    #[test]
    fn test_roundtrip_all_functions() {
        // Test roundtrip for all optimization functions
        let test_values = vec![
            0, 1, 35, 36, 1295, 1296, 46655, 46656,
            123456, 987654321, u64::MAX / 2, u64::MAX
        ];

        let encoding_functions = [
            u64_to_base36_baseline,
            u64_to_base36_unrolled,
            u64_to_base36_strength_reduced,
            u64_to_base36_branchless,
            u64_to_base36_specialized,
        ];

        for value in test_values {
            let reference = u64_to_base36_baseline(value);
            
            // Test all encoding functions produce the same result
            for func in encoding_functions {
                assert_eq!(func(value), reference, "Function mismatch for value {}", value);
            }
            
            // Test parsing roundtrip
            assert_eq!(base36_to_u64_baseline(&reference).unwrap(), value);
            assert_eq!(base36_to_u64_batched(&reference).unwrap(), value);
        }
    }

    #[test]
    fn test_edge_cases_all_functions() {
        // Test edge cases for maximum values
        let max_encoded = u64_to_base36_baseline(u64::MAX);
        assert_eq!(max_encoded, "3w5e11264sgsf");
        
        // Ensure all functions produce the same result for u64::MAX
        assert_eq!(u64_to_base36_unrolled(u64::MAX), max_encoded);
        assert_eq!(u64_to_base36_strength_reduced(u64::MAX), max_encoded);
        assert_eq!(u64_to_base36_branchless(u64::MAX), max_encoded);
        assert_eq!(u64_to_base36_specialized(u64::MAX), max_encoded);
        
        // Test parsing of max value
        assert_eq!(base36_to_u64_baseline(&max_encoded).unwrap(), u64::MAX);
        assert_eq!(base36_to_u64_batched(&max_encoded).unwrap(), u64::MAX);
    }

    #[test]
    fn test_special_range_boundaries() {
        // Test exact boundary values for specialized function
        assert_eq!(u64_to_base36_specialized(35), "z"); // Last single digit
        assert_eq!(u64_to_base36_specialized(36), "10"); // First two digit
        assert_eq!(u64_to_base36_specialized(1295), "zz"); // Last two digit  
        assert_eq!(u64_to_base36_specialized(1296), "100"); // First three digit
        assert_eq!(u64_to_base36_specialized(46655), "zzz"); // Last three digit
        assert_eq!(u64_to_base36_specialized(46656), "1000"); // First fallback case
    }
}