//! Coverage tests for magic commands
//!
//! [TEST-COV-005] Magic Commands Coverage

use ruchy::runtime::{Repl, ReplConfig, MagicRegistry, MagicCommand, MagicResult, UnicodeExpander};

#[test]
fn test_magic_registry() {
    let mut registry = MagicRegistry::new();
    
    // Test registration
    struct TestCommand;
    impl MagicCommand for TestCommand {
        fn execute_line(&self, _repl: &mut Repl, _args: &str) -> anyhow::Result<MagicResult> {
            Ok(MagicResult::Text("Test executed".to_string()))
        }
        
        fn help(&self) -> &str {
            "Test command"
        }
    }
    
    registry.register("test", Box::new(TestCommand));
    // Note: get() method doesn't exist on MagicRegistry - just test list_commands
    let commands = registry.list_commands();
    assert!(commands.contains(&"test".to_string()));
    
    // Commands already tested above
}

#[test]
fn test_unicode_expander() {
    let expander = UnicodeExpander::new();
    
    // Greek letters
    assert_eq!(expander.expand("\\alpha"), Some("α".to_string()));
    assert_eq!(expander.expand("\\beta"), Some("β".to_string()));
    assert_eq!(expander.expand("\\gamma"), Some("γ".to_string()));
    assert_eq!(expander.expand("\\delta"), Some("δ".to_string()));
    assert_eq!(expander.expand("\\epsilon"), Some("ε".to_string()));
    assert_eq!(expander.expand("\\lambda"), Some("λ".to_string()));
    assert_eq!(expander.expand("\\pi"), Some("π".to_string()));
    assert_eq!(expander.expand("\\sigma"), Some("σ".to_string()));
    assert_eq!(expander.expand("\\omega"), Some("ω".to_string()));
    
    // Capital Greek
    assert_eq!(expander.expand("\\Alpha"), Some("Α".to_string()));
    assert_eq!(expander.expand("\\Beta"), Some("Β".to_string()));
    assert_eq!(expander.expand("\\Gamma"), Some("Γ".to_string()));
    assert_eq!(expander.expand("\\Delta"), Some("Δ".to_string()));
    
    // Mathematical symbols
    assert_eq!(expander.expand("\\infty"), Some("∞".to_string()));
    assert_eq!(expander.expand("\\sum"), Some("∑".to_string()));
    assert_eq!(expander.expand("\\prod"), Some("∏".to_string()));
    assert_eq!(expander.expand("\\int"), Some("∫".to_string()));
    assert_eq!(expander.expand("\\sqrt"), Some("√".to_string()));
    assert_eq!(expander.expand("\\partial"), Some("∂".to_string()));
    assert_eq!(expander.expand("\\nabla"), Some("∇".to_string()));
    
    // Arrows
    assert_eq!(expander.expand("\\rightarrow"), Some("→".to_string()));
    assert_eq!(expander.expand("\\leftarrow"), Some("←".to_string()));
    assert_eq!(expander.expand("\\Rightarrow"), Some("⇒".to_string()));
    assert_eq!(expander.expand("\\Leftarrow"), Some("⇐".to_string()));
    
    // Operators
    assert_eq!(expander.expand("\\pm"), Some("±".to_string()));
    assert_eq!(expander.expand("\\times"), Some("×".to_string()));
    assert_eq!(expander.expand("\\div"), Some("÷".to_string()));
    assert_eq!(expander.expand("\\neq"), Some("≠".to_string()));
    assert_eq!(expander.expand("\\leq"), Some("≤".to_string()));
    assert_eq!(expander.expand("\\geq"), Some("≥".to_string()));
    
    // Non-existent
    assert_eq!(expander.expand("\\nonexistent"), None);
    assert_eq!(expander.expand("not_a_command"), None);
}

#[test]
fn test_expand_in_text() {
    let expander = UnicodeExpander::new();
    
    let text = "The equation is \\alpha + \\beta = \\gamma";
    let expanded = expander.expand_in_text(text);
    assert_eq!(expanded, "The equation is α + β = γ");
    
    let text = "\\sum_{i=1}^{n} x_i \\rightarrow \\infty";
    let expanded = expander.expand_in_text(text);
    assert!(expanded.contains("∑"));
    assert!(expanded.contains("→"));
    assert!(expanded.contains("∞"));
}

#[test]
fn test_completions() {
    let expander = UnicodeExpander::new();
    
    let completions = expander.get_completions("\\alp");
    assert!(completions.contains(&"\\alpha".to_string()));
    
    let completions = expander.get_completions("\\bet");
    assert!(completions.contains(&"\\beta".to_string()));
    
    let completions = expander.get_completions("\\in");
    assert!(completions.contains(&"\\infty".to_string()));
    assert!(completions.contains(&"\\int".to_string()));
    
    let completions = expander.get_completions("\\");
    assert!(completions.len() > 50); // Many completions
    
    let completions = expander.get_completions("xyz");
    assert!(completions.is_empty());
}

#[test]
fn test_magic_commands_execution() {
    let mut repl = Repl::new().unwrap();
    
    // Test %whos
    repl.eval("let x = 42").ok();
    repl.eval("let y = \"hello\"").ok();
    let result = repl.eval("%whos").unwrap_or_default();
    assert!(result.contains("x") || result.contains("Variable"));
    
    // Test %clear
    repl.eval("%clear").ok();
    let result = repl.eval("%whos").unwrap_or_default();
    assert!(!result.contains("x") || result.contains("No variables"));
    
    // Test %pwd
    let result = repl.eval("%pwd").unwrap_or_default();
    assert!(result.contains("/") || result.contains("\\"));
    
    // Test %history
    let result = repl.eval("%history").unwrap_or_default();
    // History should contain previous commands
}

#[test]
fn test_profile_data() {
    use ruchy::runtime::ProfileData;
    
    let mut profile = ProfileData::new();
    
    profile.record_call("function1", std::time::Duration::from_millis(100));
    profile.record_call("function1", std::time::Duration::from_millis(50));
    profile.record_call("function2", std::time::Duration::from_millis(200));
    
    let report = profile.generate_report();
    assert!(report.contains("function1"));
    assert!(report.contains("function2"));
    assert!(report.contains("2")); // 2 calls to function1
    assert!(report.contains("150")); // 150ms total for function1
}