//! Common utility functions shared across modules

use std::hash::{Hash, Hasher};
use std::thread::ThreadId;
use std::time::{SystemTime, UNIX_EPOCH};

/// Get current timestamp in nanoseconds since Unix epoch
pub fn current_timestamp_nanos() -> u64 {
    SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .unwrap_or_default()
        .as_nanos() as u64
}

/// Convert ThreadId to u64 for serialization and storage.
///
/// This uses a hash-based approach since ThreadId cannot be directly
/// converted to u64. The hash is consistent for the same ThreadId.
pub fn thread_id_to_u64(thread_id: ThreadId) -> u64 {
    let mut hasher = std::collections::hash_map::DefaultHasher::new();
    thread_id.hash(&mut hasher);
    hasher.finish()
}

/// Get the current thread's ID as u64.
///
/// Convenience function that combines getting the current ThreadId
/// and converting it to u64.
pub fn current_thread_id_u64() -> u64 {
    thread_id_to_u64(std::thread::current().id())
}

/// Format bytes in a human-readable format
pub fn format_bytes(bytes: usize) -> String {
    const KB: usize = 1024;
    const MB: usize = KB * 1024;
    const GB: usize = MB * 1024;
    const TB: usize = GB * 1024;
    const PB: usize = TB * 1024;

    if bytes < KB {
        format!("{bytes}B")
    } else if bytes < MB {
        format!("{:.1}KB", bytes as f64 / KB as f64)
    } else if bytes < GB {
        format!("{:.1}MB", bytes as f64 / MB as f64)
    } else if bytes < TB {
        format!("{:.1}GB", bytes as f64 / GB as f64)
    } else if bytes < PB {
        format!("{:.1}TB", bytes as f64 / TB as f64)
    } else {
        format!("{:.1}PB", bytes as f64 / PB as f64)
    }
}

/// Simplify Rust type names for better readability - Enhanced Unknown Type identification
pub fn simplify_type_name(type_name: &str) -> (String, String) {
    // Handle empty or explicitly unknown types first
    if type_name.is_empty() || type_name == "Unknown" {
        return ("Unknown Type".to_string(), "Unknown".to_string());
    }

    // Clean up the type name - remove extra whitespace and normalize
    let clean_type = type_name.trim();

    // Enhanced pattern matching with more comprehensive coverage
    if clean_type.contains("Vec<") || clean_type.contains("vec::Vec") {
        let inner = extract_generic_type(clean_type, "Vec");
        (format!("Vec<{inner}>"), "Collections".to_string())
    } else if clean_type.contains("HashMap") || clean_type.contains("hash_map") {
        ("HashMap<K,V>".to_string(), "Collections".to_string())
    } else if clean_type.contains("BTreeMap") || clean_type.contains("btree_map") {
        ("BTreeMap<K,V>".to_string(), "Collections".to_string())
    } else if clean_type.contains("BTreeSet") || clean_type.contains("btree_set") {
        ("BTreeSet<T>".to_string(), "Collections".to_string())
    } else if clean_type.contains("HashSet") || clean_type.contains("hash_set") {
        ("HashSet<T>".to_string(), "Collections".to_string())
    } else if clean_type.contains("VecDeque") || clean_type.contains("vec_deque") {
        ("VecDeque<T>".to_string(), "Collections".to_string())
    } else if clean_type.contains("Box<") || clean_type.contains("boxed::Box") {
        let inner = extract_generic_type(clean_type, "Box");
        if inner.contains("String") || inner.contains("string::String") {
            ("String".to_string(), "Basic Types".to_string())
        } else if inner.contains("HashMap") || inner.contains("hash_map") {
            ("HashMap<K,V>".to_string(), "Collections".to_string())
        } else if inner.contains("BTreeMap") || inner.contains("btree_map") {
            ("BTreeMap<K,V>".to_string(), "Collections".to_string())
        } else if inner.contains("BTreeSet") || inner.contains("btree_set") {
            ("BTreeSet<T>".to_string(), "Collections".to_string())
        } else if inner.contains("HashSet") || inner.contains("hash_set") {
            ("HashSet<T>".to_string(), "Collections".to_string())
        } else if inner.contains("VecDeque") || inner.contains("vec_deque") {
            ("VecDeque<T>".to_string(), "Collections".to_string())
        } else if inner.contains("Vec") || inner.contains("vec::Vec") {
            let vec_inner = extract_generic_type(&inner, "Vec");
            (format!("Vec<{vec_inner}>"), "Collections".to_string())
        } else {
            (format!("Box<{inner}>"), "Smart Pointers".to_string())
        }
    } else if clean_type.contains("Rc<") || clean_type.contains("rc::Rc") {
        let inner = extract_generic_type(clean_type, "Rc");
        if inner.contains("String") || inner.contains("string::String") {
            ("String".to_string(), "Basic Types".to_string())
        } else {
            (format!("Rc<{inner}>"), "Smart Pointers".to_string())
        }
    } else if clean_type.contains("Arc<") || clean_type.contains("sync::Arc") {
        let inner = extract_generic_type(clean_type, "Arc");
        if inner.contains("String") || inner.contains("string::String") {
            ("String".to_string(), "Basic Types".to_string())
        } else {
            (format!("Arc<{inner}>"), "Smart Pointers".to_string())
        }
    } else if clean_type.contains("String") || clean_type.contains("string::String") {
        ("String".to_string(), "Basic Types".to_string())
    } else if clean_type.contains("LinkedList") {
        ("LinkedList<T>".to_string(), "Collections".to_string())
    } else if clean_type.contains("&str") || clean_type == "str" {
        ("&str".to_string(), "Basic Types".to_string())
    } else if clean_type.contains("CString") || clean_type.contains("CStr") {
        ("CString".to_string(), "Basic Types".to_string())
    } else if clean_type.contains("OsString") || clean_type.contains("OsStr") {
        ("OsString".to_string(), "Basic Types".to_string())
    } else if clean_type.contains("PathBuf") || clean_type.contains("Path") {
        ("PathBuf".to_string(), "Basic Types".to_string())
    } else if clean_type.contains("Option<") {
        ("Option<T>".to_string(), "Optionals".to_string())
    } else if clean_type.contains("Result<") {
        ("Result<T,E>".to_string(), "Results".to_string())
    } else if clean_type.matches("i32").count() > 0
        || clean_type.matches("u32").count() > 0
        || clean_type.matches("i64").count() > 0
        || clean_type.matches("u64").count() > 0
        || clean_type.matches("f64").count() > 0
        || clean_type.matches("f32").count() > 0
        || clean_type.matches("i8").count() > 0
        || clean_type.matches("u8").count() > 0
        || clean_type.matches("i16").count() > 0
        || clean_type.matches("u16").count() > 0
        || clean_type.matches("isize").count() > 0
        || clean_type.matches("usize").count() > 0
        || clean_type.matches("bool").count() > 0
        || clean_type.matches("char").count() > 0
    {
        let primitive = clean_type.split("::").last().unwrap_or(clean_type);
        (primitive.to_string(), "Basic Types".to_string())
    } else if clean_type.contains("[") && clean_type.contains("]") {
        ("Array".to_string(), "Arrays".to_string())
    } else if clean_type.starts_with("(") && clean_type.ends_with(")") {
        ("Tuple".to_string(), "Tuples".to_string())
    } else if clean_type.contains("Mutex<") || clean_type.contains("RwLock<") {
        ("Mutex/RwLock".to_string(), "Synchronization".to_string())
    } else if clean_type.contains("Cell<") || clean_type.contains("RefCell<") {
        (
            "Cell/RefCell".to_string(),
            "Interior Mutability".to_string(),
        )
    } else if clean_type.contains("Weak<") {
        ("Weak<T>".to_string(), "Smart Pointers".to_string())
    } else if clean_type.starts_with("std::")
        || clean_type.starts_with("alloc::")
        || clean_type.starts_with("core::")
    {
        let simplified = clean_type.split("::").last().unwrap_or(clean_type);
        (simplified.to_string(), "Standard Library".to_string())
    } else if clean_type.contains("::") {
        // Handle custom types with namespaces
        let parts: Vec<&str> = clean_type.split("::").collect();
        if parts.len() >= 2 {
            // Use the original clean_type as fallback if parts is somehow empty
            let type_part = parts.last().unwrap_or(&clean_type);

            // Determine category based on namespace and type patterns
            let category = if parts
                .iter()
                .any(|&part| part.contains("error") || part.contains("Error"))
                || type_part.ends_with("Error")
                || type_part.contains("Err")
            {
                "Error Types"
            } else if type_part.ends_with("Config") || type_part.ends_with("Settings") {
                "Configuration"
            } else if type_part.ends_with("Builder") || type_part.ends_with("Factory") {
                "Builders"
            } else if parts
                .iter()
                .any(|&part| part == "std" || part == "core" || part == "alloc")
            {
                "Standard Library"
            } else if parts
                .iter()
                .any(|&part| part.contains("test") || part.contains("mock"))
            {
                "Test Types"
            } else if parts.len() > 2 {
                // Deep namespace suggests library or framework type
                "Library Types"
            } else {
                "Custom Types"
            };

            (type_part.to_string(), category.to_string())
        } else {
            // Single part, no namespace
            let category = if clean_type.ends_with("Error") || clean_type.contains("Err") {
                "Error Types"
            } else if clean_type.ends_with("Config") || clean_type.ends_with("Settings") {
                "Configuration"
            } else if clean_type.ends_with("Builder") || clean_type.ends_with("Factory") {
                "Builders"
            } else if clean_type.chars().next().is_some_and(|c| c.is_uppercase()) {
                // Starts with uppercase, likely a struct/enum
                "Custom Types"
            } else {
                // Lowercase, might be a function type or other
                "Other Types"
            };

            (clean_type.to_string(), category.to_string())
        }
    } else {
        // For simple type names without namespace
        if !clean_type.is_empty() {
            (clean_type.to_string(), "Custom Types".to_string())
        } else {
            ("Unknown Type".to_string(), "Unknown".to_string())
        }
    }
}

/// Extract generic type parameter for display
pub fn extract_generic_type(type_name: &str, container: &str) -> String {
    if let Some(start) = type_name.find(&format!("{container}<")) {
        let content_start = start + container.len() + 1;
        let content = &type_name[content_start..];

        let mut depth = 1;
        let mut end = 0;

        for (i, c) in content.char_indices() {
            match c {
                '<' => depth += 1,
                '>' => {
                    depth -= 1;
                    if depth == 0 {
                        end = i;
                        break;
                    }
                }
                _ => {}
            }
        }

        if end > 0 {
            let inner = &content[..end];
            return inner.split("::").last().unwrap_or(inner).to_string();
        }
    }
    "?".to_string()
}

/// Get a simplified type name for display
pub fn get_simple_type(type_name: &str) -> String {
    if type_name.contains("String") {
        "String".to_string()
    } else if type_name.contains("Vec") {
        "Vec".to_string()
    } else if type_name.contains("Box") {
        "Box".to_string()
    } else if type_name.contains("Rc") {
        "Rc".to_string()
    } else if type_name.contains("Arc") {
        "Arc".to_string()
    } else if type_name.contains("HashMap") {
        "HashMap".to_string()
    } else {
        type_name
            .split("::")
            .last()
            .unwrap_or("Unknown")
            .to_string()
    }
}

/// Get color for category - Enhanced with new categories
pub fn get_category_color(category: &str) -> String {
    match category {
        "Collections" => "#3498db".to_string(),               // Blue
        "Basic Types" => "#27ae60".to_string(),               // Green for Basic Types
        "Strings" => "#27ae60".to_string(),                   // Green (legacy support)
        "Text" => "#27ae60".to_string(),                      // Green (legacy support)
        "Smart Pointers" => "#e74c3c".to_string(),            // Red
        "Reference Counted" => "#f39c12".to_string(),         // Orange
        "Thread-Safe Shared" => "#9b59b6".to_string(),        // Purple
        "Primitives" => "#1abc9c".to_string(),                // Teal
        "Arrays" => "#34495e".to_string(),                    // Dark Gray
        "Tuples" => "#16a085".to_string(),                    // Dark Teal
        "Optionals" => "#8e44ad".to_string(),                 // Dark Purple
        "Results" => "#d35400".to_string(),                   // Dark Orange
        "Standard Library" => "#2980b9".to_string(),          // Dark Blue
        "Custom Types" => "#c0392b".to_string(),              // Dark Red
        "Synchronization" => "#e67e22".to_string(),           // Orange
        "Interior Mutability" => "#95a5a6".to_string(),       // Light Gray
        "Error Types" => "#e74c3c".to_string(),               // Red
        "Configuration" => "#3498db".to_string(),             // Blue
        "Builders" => "#9b59b6".to_string(),                  // Purple
        "Runtime/System Allocation" => "#bdc3c7".to_string(), // Light Gray for system allocations
        "Unknown" => "#bdc3c7".to_string(),                   // Light Gray (legacy support)
        _ => "#7f8c8d".to_string(),                           // Medium Gray for other unknowns
    }
}

/// Get type-specific gradient colors for enhanced visualization
pub fn get_type_gradient_colors(type_name: &str) -> (&'static str, &'static str) {
    match type_name {
        "String" => ("#00BCD4", "#00ACC1"),  // Teal gradient
        "Vec" => ("#2196F3", "#1976D2"),     // Blue gradient
        "Box" => ("#F44336", "#D32F2F"),     // Red gradient
        "HashMap" => ("#4CAF50", "#388E3C"), // Green gradient
        "Rc" => ("#FF9800", "#F57C00"),      // Orange gradient
        "Arc" => ("#9C27B0", "#7B1FA2"),     // Purple gradient
        _ => ("#607D8B", "#455A64"),         // Blue-gray gradient for custom types
    }
}

/// Get color based on type for consistent visualization
pub fn get_type_color(type_name: &str) -> &'static str {
    match type_name {
        "String" => "#2ecc71",
        "Vec" => "#3498db",
        "Box" => "#e74c3c",
        "HashMap" => "#f39c12",
        "Rc" => "#9b59b6",
        "Arc" => "#1abc9c",
        _ => "#95a5a6",
    }
}

/// Enhanced type hierarchy classification for treemap visualization
#[derive(Debug, Clone)]
pub struct TypeHierarchy {
    /// Major category: Collections, Strings, Smart Pointers, etc.
    pub major_category: String,
    /// Sub category: Maps, Sequences, Owned, Shared, etc.
    pub sub_category: String,
    /// Specific type: HashMap, Vec, Box, etc.
    pub specific_type: String,
    /// Full type name: HashMap<String, i32>
    pub full_type: String,
}

/// Get comprehensive type hierarchy for treemap visualization
pub fn get_type_category_hierarchy(type_name: &str) -> TypeHierarchy {
    // Handle empty or unknown types first
    if type_name.is_empty() || type_name == "Unknown" {
        return TypeHierarchy {
            major_category: "Unknown".to_string(),
            sub_category: "Unidentified".to_string(),
            specific_type: "Unknown Type".to_string(),
            full_type: type_name.to_string(),
        };
    }

    // Collections
    if type_name.contains("HashMap") || type_name.contains("hash::map") {
        let inner = extract_generic_params(type_name, "HashMap");
        TypeHierarchy {
            major_category: "Collections".to_string(),
            sub_category: "Maps".to_string(),
            specific_type: "HashMap".to_string(),
            full_type: if inner.is_empty() {
                "HashMap".to_string()
            } else {
                format!("HashMap<{inner}>")
            },
        }
    } else if type_name.contains("BTreeMap") || type_name.contains("btree::map") {
        let inner = extract_generic_params(type_name, "BTreeMap");
        TypeHierarchy {
            major_category: "Collections".to_string(),
            sub_category: "Maps".to_string(),
            specific_type: "BTreeMap".to_string(),
            full_type: if inner.is_empty() {
                "BTreeMap".to_string()
            } else {
                format!("BTreeMap<{inner}>")
            },
        }
    } else if type_name.contains("HashSet") || type_name.contains("hash::set") {
        let inner = extract_generic_params(type_name, "HashSet");
        TypeHierarchy {
            major_category: "Collections".to_string(),
            sub_category: "Sets".to_string(),
            specific_type: "HashSet".to_string(),
            full_type: if inner.is_empty() {
                "HashSet".to_string()
            } else {
                format!("HashSet<{inner}>")
            },
        }
    } else if type_name.contains("Vec") && !type_name.contains("VecDeque") {
        let inner = extract_generic_params(type_name, "Vec");
        TypeHierarchy {
            major_category: "Collections".to_string(),
            sub_category: "Sequences".to_string(),
            specific_type: "Vec".to_string(),
            full_type: if inner.is_empty() {
                "Vec".to_string()
            } else {
                format!("Vec<{inner}>")
            },
        }
    } else if type_name.contains("VecDeque") {
        let inner = extract_generic_params(type_name, "VecDeque");
        TypeHierarchy {
            major_category: "Collections".to_string(),
            sub_category: "Sequences".to_string(),
            specific_type: "VecDeque".to_string(),
            full_type: if inner.is_empty() {
                "VecDeque".to_string()
            } else {
                format!("VecDeque<{inner}>")
            },
        }
    }
    // Strings
    else if type_name.contains("String") && !type_name.contains("<") {
        TypeHierarchy {
            major_category: "Strings".to_string(),
            sub_category: "Owned".to_string(),
            specific_type: "String".to_string(),
            full_type: "String".to_string(),
        }
    } else if type_name.contains("&str") || (type_name.contains("str") && type_name.contains("&")) {
        TypeHierarchy {
            major_category: "Strings".to_string(),
            sub_category: "Borrowed".to_string(),
            specific_type: "&str".to_string(),
            full_type: "&str".to_string(),
        }
    }
    // Smart Pointers
    else if type_name.contains("Box<") {
        let inner = extract_generic_params(type_name, "Box");
        TypeHierarchy {
            major_category: "Smart Pointers".to_string(),
            sub_category: "Owned".to_string(),
            specific_type: "Box".to_string(),
            full_type: if inner.is_empty() {
                "Box".to_string()
            } else {
                format!("Box<{inner}>")
            },
        }
    } else if type_name.contains("Rc<") {
        let inner = extract_generic_params(type_name, "Rc");
        TypeHierarchy {
            major_category: "Smart Pointers".to_string(),
            sub_category: "Reference Counted".to_string(),
            specific_type: "Rc".to_string(),
            full_type: if inner.is_empty() {
                "Rc".to_string()
            } else {
                format!("Rc<{inner}>")
            },
        }
    } else if type_name.contains("Arc<") {
        let inner = extract_generic_params(type_name, "Arc");
        TypeHierarchy {
            major_category: "Smart Pointers".to_string(),
            sub_category: "Thread-Safe Shared".to_string(),
            specific_type: "Arc".to_string(),
            full_type: if inner.is_empty() {
                "Arc".to_string()
            } else {
                format!("Arc<{inner}>")
            },
        }
    }
    // Primitives
    else if is_primitive_type(type_name) {
        let clean_type = type_name.split("::").last().unwrap_or(type_name);
        let sub_cat = if clean_type.contains("i") || clean_type.contains("u") {
            "Integers"
        } else if clean_type.contains("f") {
            "Floats"
        } else if clean_type == "bool" {
            "Boolean"
        } else {
            "Other"
        };
        TypeHierarchy {
            major_category: "Primitives".to_string(),
            sub_category: sub_cat.to_string(),
            specific_type: clean_type.to_string(),
            full_type: clean_type.to_string(),
        }
    }
    // Fallback
    else {
        let simplified = type_name.split("::").last().unwrap_or(type_name);
        TypeHierarchy {
            major_category: "Custom Types".to_string(),
            sub_category: "User Defined".to_string(),
            specific_type: simplified.to_string(),
            full_type: simplified.to_string(),
        }
    }
}

/// Extract generic parameters from type names (enhanced version)
pub fn extract_generic_params(type_name: &str, container: &str) -> String {
    if let Some(start) = type_name.find(&format!("{container}<")) {
        let start = start + container.len() + 1;
        if let Some(end) = find_matching_bracket(type_name, start - 1) {
            let inner = &type_name[start..end];
            // Simplify the inner type
            return inner.split("::").last().unwrap_or(inner).to_string();
        }
    }
    String::new()
}

/// Find matching closing bracket for generic types
fn find_matching_bracket(s: &str, start: usize) -> Option<usize> {
    let chars: Vec<char> = s.chars().collect();
    if start >= chars.len() || chars[start] != '<' {
        return None;
    }

    let mut depth = 1;
    for (i, item) in chars.iter().enumerate().skip(start + 1) {
        match item {
            '<' => depth += 1,
            '>' => {
                depth -= 1;
                if depth == 0 {
                    return Some(i);
                }
            }
            _ => {}
        }
    }
    None
}

/// Check if a type is a primitive type
pub fn is_primitive_type(type_name: &str) -> bool {
    let clean_type = type_name.split("::").last().unwrap_or(type_name);
    matches!(
        clean_type,
        "i8" | "i16"
            | "i32"
            | "i64"
            | "i128"
            | "isize"
            | "u8"
            | "u16"
            | "u32"
            | "u64"
            | "u128"
            | "usize"
            | "f32"
            | "f64"
            | "bool"
            | "char"
    )
}

/// Extract array information for display
pub fn extract_array_info(type_name: &str) -> String {
    if let Some(start) = type_name.find('[') {
        if let Some(end) = type_name.find(']') {
            if end > start {
                return type_name[start..=end].to_string();
            }
        }
    }
    "Array".to_string()
}

/// Extract standard library module name
pub fn extract_std_module(type_name: &str) -> String {
    let parts: Vec<&str> = type_name.split("::").collect();
    if parts.len() >= 2 {
        match parts[1] {
            "collections" => "Collections".to_string(),
            "sync" => "Synchronization".to_string(),
            "thread" => "Threading".to_string(),
            "fs" => "File System".to_string(),
            "net" => "Networking".to_string(),
            "io" => "Input/Output".to_string(),
            _ => "Other".to_string(),
        }
    } else {
        "Other".to_string()
    }
}

// ============================================================================
// Thread Utilities (merged from thread_utils.rs)
// ============================================================================

use std::thread;
use std::time::Duration;

/// Extension trait for JoinHandle to add timeout functionality
pub trait JoinHandleExt<T> {
    /// Join with a timeout, returning an error if the timeout is exceeded
    ///
    /// This implementation properly handles timeout by using a dedicated timeout thread
    /// that will exit immediately, avoiding resource leaks. The original thread continues
    /// running in the background if it doesn't finish within the timeout.
    fn join_timeout(self, timeout: Duration) -> Result<T, Box<dyn std::any::Any + Send + 'static>>;
}

impl<T: Send + 'static> JoinHandleExt<T> for thread::JoinHandle<T> {
    fn join_timeout(self, timeout: Duration) -> Result<T, Box<dyn std::any::Any + Send + 'static>> {
        // If the thread is already finished, just join it
        if self.is_finished() {
            return self.join().map_err(|e| Box::new(e) as _);
        }

        // Use a channel to communicate result or timeout
        let (tx, rx) = std::sync::mpsc::channel();

        // Spawn a thread that will join the original thread and send the result
        thread::spawn(move || {
            let result = self.join();
            // Ignore send errors - the receiver might have been dropped due to timeout
            let _ = tx.send(result);
        });

        // Wait for either the thread to finish or timeout to occur
        match rx.recv_timeout(timeout) {
            Ok(result) => result.map_err(|e| Box::new(e) as _),
            Err(std::sync::mpsc::RecvTimeoutError::Timeout) => {
                // Timeout occurred - the original thread continues running in background
                // This is unavoidable in Rust without thread cancellation
                Err(Box::new("Thread join timed out") as _)
            }
            Err(std::sync::mpsc::RecvTimeoutError::Disconnected) => {
                // Sender disconnected unexpectedly
                Err(Box::new("Thread communication error") as _)
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::thread;
    use std::time::Duration;

    #[test]
    fn test_current_timestamp_nanos() {
        let timestamp1 = current_timestamp_nanos();
        thread::sleep(Duration::from_millis(1));
        let timestamp2 = current_timestamp_nanos();

        assert!(timestamp2 > timestamp1);
        assert!(timestamp1 > 0);
    }

    #[test]
    fn test_format_bytes() {
        assert_eq!(format_bytes(0), "0B");
        assert_eq!(format_bytes(512), "512B");
        assert_eq!(format_bytes(1024), "1.0KB");
        assert_eq!(format_bytes(1536), "1.5KB");
        assert_eq!(format_bytes(1024 * 1024), "1.0MB");
        assert_eq!(format_bytes(1024 * 1024 + 512 * 1024), "1.5MB");
        assert_eq!(format_bytes(1024 * 1024 * 1024), "1.0GB");
        assert_eq!(format_bytes(1024 * 1024 * 1024 * 2), "2.0GB");
        assert_eq!(format_bytes(1024usize.pow(4)), "1.0TB");
        assert_eq!(format_bytes(1024usize.pow(4) * 5), "5.0TB");
        assert_eq!(format_bytes(1024usize.pow(5)), "1.0PB");
        assert_eq!(format_bytes(1024usize.pow(5) * 10), "10.0PB");
    }

    #[test]
    fn test_simplify_type_name_basic_types() {
        let (simplified, category) = simplify_type_name("String");
        assert_eq!(simplified, "String");
        assert_eq!(category, "Basic Types");

        let (simplified, category) = simplify_type_name("&str");
        assert_eq!(simplified, "&str");
        assert_eq!(category, "Basic Types");

        let (simplified, category) = simplify_type_name("i32");
        assert_eq!(simplified, "i32");
        assert_eq!(category, "Basic Types");

        let (simplified, category) = simplify_type_name("bool");
        assert_eq!(simplified, "bool");
        assert_eq!(category, "Basic Types");
    }

    #[test]
    fn test_simplify_type_name_collections() {
        let (simplified, category) = simplify_type_name("Vec<i32>");
        assert_eq!(simplified, "Vec<i32>");
        assert_eq!(category, "Collections");

        let (simplified, category) = simplify_type_name("HashMap<String, i32>");
        assert_eq!(simplified, "HashMap<K,V>");
        assert_eq!(category, "Collections");

        let (simplified, category) = simplify_type_name("BTreeMap<String, i32>");
        assert_eq!(simplified, "BTreeMap<K,V>");
        assert_eq!(category, "Collections");

        let (simplified, category) = simplify_type_name("HashSet<String>");
        assert_eq!(simplified, "HashSet<T>");
        assert_eq!(category, "Collections");
    }

    #[test]
    fn test_simplify_type_name_smart_pointers() {
        let (simplified, category) = simplify_type_name("Box<i32>");
        assert_eq!(simplified, "Box<i32>");
        assert_eq!(category, "Smart Pointers");

        let (simplified, category) = simplify_type_name("Rc<String>");
        assert_eq!(simplified, "String");
        assert_eq!(category, "Basic Types");

        let (simplified, category) = simplify_type_name("Arc<Mutex<i32>>");
        assert_eq!(simplified, "Arc<Mutex<i32>>");
        assert_eq!(category, "Smart Pointers");

        let (simplified, category) = simplify_type_name("Box<HashMap<String, i32>>");
        assert_eq!(simplified, "HashMap<K,V>");
        assert_eq!(category, "Collections");
    }

    #[test]
    fn test_simplify_type_name_special_cases() {
        let (simplified, category) = simplify_type_name("");
        assert_eq!(simplified, "Unknown Type");
        assert_eq!(category, "Unknown");

        let (simplified, category) = simplify_type_name("Unknown");
        assert_eq!(simplified, "Unknown Type");
        assert_eq!(category, "Unknown");

        let (simplified, category) = simplify_type_name("Option<i32>");
        assert_eq!(simplified, "Option<T>");
        assert_eq!(category, "Optionals");

        // String detection takes priority
        let (simplified, category) = simplify_type_name("Result<String, Error>");
        assert_eq!(simplified, "String");
        assert_eq!(category, "Basic Types");
    }

    #[test]
    fn test_simplify_type_name_arrays_tuples() {
        // The function returns the full array notation, but category is Basic Types due to i32 detection
        let (simplified, category) = simplify_type_name("[i32; 10]");
        assert_eq!(simplified, "[i32; 10]");
        assert_eq!(category, "Basic Types");

        // String detection takes priority over tuple
        let (simplified, category) = simplify_type_name("(i32, String)");
        assert_eq!(simplified, "String");
        assert_eq!(category, "Basic Types");
    }

    #[test]
    fn test_simplify_type_name_synchronization() {
        // Mutex detection takes priority over i32
        let (simplified, category) = simplify_type_name("Mutex<i32>");
        assert_eq!(simplified, "Mutex<i32>");
        assert_eq!(category, "Basic Types");

        // String detection takes priority
        let (simplified, category) = simplify_type_name("RwLock<String>");
        assert_eq!(simplified, "String");
        assert_eq!(category, "Basic Types");

        let (simplified, category) = simplify_type_name("Cell<i32>");
        assert_eq!(simplified, "Cell<i32>");
        assert_eq!(category, "Basic Types");
    }

    #[test]
    fn test_simplify_type_name_namespaced() {
        // HashMap detection works for namespaced types
        let (simplified, category) = simplify_type_name("std::collections::HashMap");
        assert_eq!(simplified, "HashMap<K,V>");
        assert_eq!(category, "Collections");

        let (simplified, category) = simplify_type_name("my_crate::MyStruct");
        assert_eq!(simplified, "MyStruct");
        assert_eq!(category, "Custom Types");

        let (simplified, category) = simplify_type_name("my_crate::error::MyError");
        assert_eq!(simplified, "MyError");
        assert_eq!(category, "Error Types");

        let (simplified, category) = simplify_type_name("my_crate::config::AppConfig");
        assert_eq!(simplified, "AppConfig");
        assert_eq!(category, "Configuration");
    }

    #[test]
    fn test_extract_generic_type() {
        assert_eq!(extract_generic_type("Vec<i32>", "Vec"), "i32");
        assert_eq!(extract_generic_type("Box<String>", "Box"), "String");
        assert_eq!(
            extract_generic_type("HashMap<String, i32>", "HashMap"),
            "String, i32"
        );
        assert_eq!(extract_generic_type("Vec", "Vec"), "?");
        assert_eq!(
            extract_generic_type("std::vec::Vec<std::string::String>", "Vec"),
            "String"
        );
    }

    #[test]
    fn test_get_simple_type() {
        assert_eq!(get_simple_type("std::string::String"), "String");
        assert_eq!(get_simple_type("std::vec::Vec<i32>"), "Vec");
        // String detection takes priority over Box
        assert_eq!(get_simple_type("std::boxed::Box<String>"), "String");
        assert_eq!(get_simple_type("std::rc::Rc<i32>"), "Rc");
        assert_eq!(get_simple_type("std::sync::Arc<String>"), "String");
        assert_eq!(get_simple_type("std::collections::HashMap<K,V>"), "HashMap");
        assert_eq!(get_simple_type("my_crate::MyType"), "MyType");
        assert_eq!(get_simple_type("UnknownType"), "UnknownType");
    }

    #[test]
    fn test_get_category_color() {
        assert_eq!(get_category_color("Collections"), "#3498db");
        assert_eq!(get_category_color("Basic Types"), "#27ae60");
        assert_eq!(get_category_color("Smart Pointers"), "#e74c3c");
        assert_eq!(get_category_color("Synchronization"), "#e67e22");
        assert_eq!(get_category_color("Unknown"), "#bdc3c7");
        assert_eq!(get_category_color("NonExistentCategory"), "#7f8c8d");
    }

    #[test]
    fn test_get_type_gradient_colors() {
        let (start, end) = get_type_gradient_colors("String");
        assert_eq!(start, "#00BCD4");
        assert_eq!(end, "#00ACC1");

        let (start, end) = get_type_gradient_colors("Vec");
        assert_eq!(start, "#2196F3");
        assert_eq!(end, "#1976D2");

        let (start, end) = get_type_gradient_colors("UnknownType");
        assert_eq!(start, "#607D8B");
        assert_eq!(end, "#455A64");
    }

    #[test]
    fn test_get_type_color() {
        assert_eq!(get_type_color("String"), "#2ecc71");
        assert_eq!(get_type_color("Vec"), "#3498db");
        assert_eq!(get_type_color("Box"), "#e74c3c");
        assert_eq!(get_type_color("HashMap"), "#f39c12");
        assert_eq!(get_type_color("Rc"), "#9b59b6");
        assert_eq!(get_type_color("Arc"), "#1abc9c");
        assert_eq!(get_type_color("UnknownType"), "#95a5a6");
    }

    #[test]
    fn test_get_type_category_hierarchy_collections() {
        let hierarchy = get_type_category_hierarchy("HashMap<String, i32>");
        assert_eq!(hierarchy.major_category, "Collections");
        assert_eq!(hierarchy.sub_category, "Maps");
        assert_eq!(hierarchy.specific_type, "HashMap");
        assert_eq!(hierarchy.full_type, "HashMap<String, i32>");

        let hierarchy = get_type_category_hierarchy("Vec<u8>");
        assert_eq!(hierarchy.major_category, "Collections");
        assert_eq!(hierarchy.sub_category, "Sequences");
        assert_eq!(hierarchy.specific_type, "Vec");
        assert_eq!(hierarchy.full_type, "Vec<u8>");

        let hierarchy = get_type_category_hierarchy("HashSet<String>");
        assert_eq!(hierarchy.major_category, "Collections");
        assert_eq!(hierarchy.sub_category, "Sets");
        assert_eq!(hierarchy.specific_type, "HashSet");
        assert_eq!(hierarchy.full_type, "HashSet<String>");
    }

    #[test]
    fn test_get_type_category_hierarchy_strings() {
        let hierarchy = get_type_category_hierarchy("String");
        assert_eq!(hierarchy.major_category, "Strings");
        assert_eq!(hierarchy.sub_category, "Owned");
        assert_eq!(hierarchy.specific_type, "String");
        assert_eq!(hierarchy.full_type, "String");

        let hierarchy = get_type_category_hierarchy("&str");
        assert_eq!(hierarchy.major_category, "Strings");
        assert_eq!(hierarchy.sub_category, "Borrowed");
        assert_eq!(hierarchy.specific_type, "&str");
        assert_eq!(hierarchy.full_type, "&str");
    }

    #[test]
    fn test_get_type_category_hierarchy_smart_pointers() {
        let hierarchy = get_type_category_hierarchy("Box<i32>");
        assert_eq!(hierarchy.major_category, "Smart Pointers");
        assert_eq!(hierarchy.sub_category, "Owned");
        assert_eq!(hierarchy.specific_type, "Box");
        assert_eq!(hierarchy.full_type, "Box<i32>");

        let hierarchy = get_type_category_hierarchy("Rc<String>");
        assert_eq!(hierarchy.major_category, "Smart Pointers");
        assert_eq!(hierarchy.sub_category, "Reference Counted");
        assert_eq!(hierarchy.specific_type, "Rc");
        assert_eq!(hierarchy.full_type, "Rc<String>");

        let hierarchy = get_type_category_hierarchy("Arc<Mutex<i32>>");
        assert_eq!(hierarchy.major_category, "Smart Pointers");
        assert_eq!(hierarchy.sub_category, "Thread-Safe Shared");
        assert_eq!(hierarchy.specific_type, "Arc");
        assert_eq!(hierarchy.full_type, "Arc<Mutex<i32>>");
    }

    #[test]
    fn test_get_type_category_hierarchy_primitives() {
        let hierarchy = get_type_category_hierarchy("i32");
        assert_eq!(hierarchy.major_category, "Primitives");
        assert_eq!(hierarchy.sub_category, "Integers");
        assert_eq!(hierarchy.specific_type, "i32");
        assert_eq!(hierarchy.full_type, "i32");

        let hierarchy = get_type_category_hierarchy("f64");
        assert_eq!(hierarchy.major_category, "Primitives");
        assert_eq!(hierarchy.sub_category, "Floats");
        assert_eq!(hierarchy.specific_type, "f64");
        assert_eq!(hierarchy.full_type, "f64");

        let hierarchy = get_type_category_hierarchy("bool");
        assert_eq!(hierarchy.major_category, "Primitives");
        assert_eq!(hierarchy.sub_category, "Boolean");
        assert_eq!(hierarchy.specific_type, "bool");
        assert_eq!(hierarchy.full_type, "bool");
    }

    #[test]
    fn test_get_type_category_hierarchy_unknown() {
        let hierarchy = get_type_category_hierarchy("");
        assert_eq!(hierarchy.major_category, "Unknown");
        assert_eq!(hierarchy.sub_category, "Unidentified");
        assert_eq!(hierarchy.specific_type, "Unknown Type");

        let hierarchy = get_type_category_hierarchy("Unknown");
        assert_eq!(hierarchy.major_category, "Unknown");
        assert_eq!(hierarchy.sub_category, "Unidentified");
        assert_eq!(hierarchy.specific_type, "Unknown Type");
    }

    #[test]
    fn test_extract_generic_params() {
        assert_eq!(
            extract_generic_params("HashMap<String, i32>", "HashMap"),
            "String, i32"
        );
        assert_eq!(extract_generic_params("Vec<u8>", "Vec"), "u8");
        assert_eq!(extract_generic_params("Box<String>", "Box"), "String");
        assert_eq!(extract_generic_params("Vec", "Vec"), "");
        assert_eq!(
            extract_generic_params("std::vec::Vec<std::string::String>", "Vec"),
            "String"
        );
    }

    #[test]
    fn test_find_matching_bracket() {
        assert_eq!(find_matching_bracket("Vec<i32>", 3), Some(7));
        assert_eq!(
            find_matching_bracket("HashMap<String, Vec<i32>>", 7),
            Some(24)
        );
        assert_eq!(find_matching_bracket("Vec<i32", 3), None);
        assert_eq!(find_matching_bracket("Vec", 3), None);
    }

    #[test]
    fn test_is_primitive_type() {
        assert!(is_primitive_type("i32"));
        assert!(is_primitive_type("u64"));
        assert!(is_primitive_type("f32"));
        assert!(is_primitive_type("bool"));
        assert!(is_primitive_type("char"));
        assert!(is_primitive_type("isize"));
        assert!(is_primitive_type("usize"));

        assert!(!is_primitive_type("String"));
        assert!(!is_primitive_type("Vec<i32>"));
        assert!(!is_primitive_type("CustomType"));

        // Test with namespace
        assert!(is_primitive_type("std::primitive::i32"));
        assert!(!is_primitive_type("std::string::String"));
    }

    #[test]
    fn test_extract_array_info() {
        assert_eq!(extract_array_info("[i32; 10]"), "[i32; 10]");
        assert_eq!(extract_array_info("[u8; 256]"), "[u8; 256]");
        assert_eq!(extract_array_info("Vec<i32>"), "Array");
        assert_eq!(extract_array_info("no_brackets"), "Array");
    }

    #[test]
    fn test_extract_std_module() {
        assert_eq!(
            extract_std_module("std::collections::HashMap"),
            "Collections"
        );
        assert_eq!(extract_std_module("std::sync::Mutex"), "Synchronization");
        assert_eq!(extract_std_module("std::thread::JoinHandle"), "Threading");
        assert_eq!(extract_std_module("std::fs::File"), "File System");
        assert_eq!(extract_std_module("std::net::TcpStream"), "Networking");
        assert_eq!(extract_std_module("std::io::BufReader"), "Input/Output");
        assert_eq!(extract_std_module("std::unknown::Type"), "Other");
        assert_eq!(extract_std_module("CustomType"), "Other");
    }

    #[test]
    fn test_join_handle_ext_immediate_completion() {
        let handle = thread::spawn(|| 42);

        // Give the thread time to complete
        thread::sleep(Duration::from_millis(10));

        let result = handle.join_timeout(Duration::from_millis(100));
        assert!(result.is_ok());
        assert_eq!(result.unwrap(), 42);
    }

    #[test]
    fn test_join_handle_ext_timeout() {
        let handle = thread::spawn(|| {
            thread::sleep(Duration::from_millis(200));
            42
        });

        let result = handle.join_timeout(Duration::from_millis(50));
        assert!(result.is_err());
    }

    #[test]
    fn test_join_handle_ext_within_timeout() {
        let handle = thread::spawn(|| {
            thread::sleep(Duration::from_millis(50));
            42
        });

        let result = handle.join_timeout(Duration::from_millis(200));
        assert!(result.is_ok());
        assert_eq!(result.unwrap(), 42);
    }

    #[test]
    fn test_type_hierarchy_custom_types() {
        let hierarchy = get_type_category_hierarchy("MyCustomType");
        assert_eq!(hierarchy.major_category, "Custom Types");
        assert_eq!(hierarchy.sub_category, "User Defined");
        assert_eq!(hierarchy.specific_type, "MyCustomType");
        assert_eq!(hierarchy.full_type, "MyCustomType");
    }

    #[test]
    fn test_simplify_type_name_edge_cases() {
        // Test whitespace handling
        let (simplified, category) = simplify_type_name("  String  ");
        assert_eq!(simplified, "String");
        assert_eq!(category, "Basic Types");

        // Test complex nested types - correctly handles nested brackets
        let (simplified, category) = simplify_type_name("Box<Vec<HashMap<String, i32>>>");
        assert_eq!(simplified, "Vec<HashMap<String, i32>>");
        assert_eq!(category, "Collections");

        // Test weak pointers
        let (simplified, category) = simplify_type_name("Weak<String>");
        assert_eq!(simplified, "String");
        assert_eq!(category, "Basic Types");
    }

    #[test]
    fn test_thread_id_to_u64() {
        let id1 = thread::current().id();
        let id2 = thread::current().id();
        assert_eq!(thread_id_to_u64(id1), thread_id_to_u64(id2));

        let handle = thread::spawn(|| thread_id_to_u64(thread::current().id()));
        let other_id = handle.join().unwrap();
        assert_ne!(thread_id_to_u64(thread::current().id()), other_id);
    }

    #[test]
    fn test_current_thread_id_u64() {
        let id1 = current_thread_id_u64();
        let id2 = current_thread_id_u64();
        assert_eq!(id1, id2);
    }
}
