//! Comprehensive SIMD Column Operations Performance Demonstration
//!
//! This example demonstrates the performance improvements achieved by the comprehensive
//! SIMD column operations implementation, extending beyond aggregations to include
//! arithmetic, comparison, and mathematical operations.
//!
//! Features demonstrated:
//! - Element-wise arithmetic operations (add, subtract, multiply, divide)
//! - Scalar operations with broadcasting
//! - Mathematical functions (abs, sqrt)
//! - Comparison operations with various operators
//! - Mixed-type operations with automatic promotion
//! - Performance comparison with scalar implementations
//!
//! Run with: cargo run --example simd_column_operations_demo

use pandrs::column::{
    Column, Float64Column, Int64Column, SIMDColumnArithmetic, SIMDFloat64Ops, SIMDInt64Ops,
};
use pandrs::core::error::Result;
use pandrs::optimized::jit::ComparisonOp;
use std::time::Instant;

#[allow(clippy::result_large_err)]
fn main() -> Result<()> {
    println!("PandRS Comprehensive SIMD Column Operations Demo");
    println!("===============================================");
    println!();

    // Demonstrate different SIMD operations
    demo_basic_arithmetic()?;
    println!();

    demo_scalar_operations()?;
    println!();

    demo_mathematical_functions()?;
    println!();

    demo_comparison_operations()?;
    println!();

    demo_mixed_type_operations()?;
    println!();

    demo_performance_comparison()?;
    println!();

    demo_large_scale_operations()?;
    println!();

    print_summary();

    Ok(())
}

/// Demonstrate basic element-wise arithmetic operations
#[allow(clippy::result_large_err)]
fn demo_basic_arithmetic() -> Result<()> {
    println!("🧮 Basic Arithmetic Operations");
    println!("==============================");

    let data1 = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0];
    let data2 = vec![2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0];

    let col1 = Float64Column::new(data1);
    let col2 = Float64Column::new(data2);

    println!("Input columns:");
    println!("  Column 1: {:?}", col1.data());
    println!("  Column 2: {:?}", col2.data());
    println!();

    // Addition
    let add_result = col1.simd_add(&col2)?;
    println!("Addition (col1 + col2): {:?}", add_result.data());

    // Subtraction
    let sub_result = col1.simd_subtract(&col2)?;
    println!("Subtraction (col1 - col2): {:?}", sub_result.data());

    // Multiplication
    let mul_result = col1.simd_multiply(&col2)?;
    println!("Multiplication (col1 * col2): {:?}", mul_result.data());

    // Division
    let div_result = col1.simd_divide(&col2)?;
    println!("Division (col1 / col2): {:?}", div_result.data());

    Ok(())
}

/// Demonstrate scalar operations with broadcasting
#[allow(clippy::result_large_err)]
fn demo_scalar_operations() -> Result<()> {
    println!("📊 Scalar Operations");
    println!("===================");

    let data = vec![1.0, 2.0, 3.0, 4.0, 5.0];
    let col = Float64Column::new(data);

    println!("Input column: {:?}", col.data());
    println!();

    // Scalar addition
    let add_result = col.simd_add_scalar(10.0)?;
    println!("Add scalar 10.0: {:?}", add_result.data());

    // Scalar multiplication
    let mul_result = col.simd_multiply_scalar(3.0)?;
    println!("Multiply by scalar 3.0: {:?}", mul_result.data());

    // Test with i64 column
    let int_data = vec![1i64, 2, 3, 4, 5];
    let int_col = Int64Column::new(int_data);

    println!();
    println!("Integer column operations:");
    println!("Input: {:?}", int_col.data());

    let int_add_result = int_col.simd_add_scalar(100)?;
    println!("Add scalar 100: {:?}", int_add_result.data());

    Ok(())
}

/// Demonstrate mathematical functions
#[allow(clippy::result_large_err)]
fn demo_mathematical_functions() -> Result<()> {
    println!("🔢 Mathematical Functions");
    println!("========================");

    let data = vec![-4.0, -2.0, 0.0, 2.0, 4.0, 9.0, 16.0, 25.0];
    let col = Float64Column::new(data);

    println!("Input column: {:?}", col.data());
    println!();

    // Absolute value
    let abs_result = col.simd_abs()?;
    println!("Absolute value: {:?}", abs_result.data());

    // Square root (only for non-negative values)
    let positive_data = vec![0.0, 1.0, 4.0, 9.0, 16.0, 25.0, 36.0, 49.0];
    let positive_col = Float64Column::new(positive_data);
    println!();
    println!("Input for sqrt: {:?}", positive_col.data());

    let sqrt_result = positive_col.simd_sqrt()?;
    println!("Square root: {:?}", sqrt_result.data());

    // Integer absolute value
    let int_data = vec![-10i64, -5, 0, 5, 10];
    let int_col = Int64Column::new(int_data);
    println!();
    println!("Integer absolute value:");
    println!("Input: {:?}", int_col.data());

    let int_abs_result = int_col.simd_abs()?;
    println!("Result: {:?}", int_abs_result.data());

    Ok(())
}

/// Demonstrate comparison operations
#[allow(clippy::result_large_err)]
fn demo_comparison_operations() -> Result<()> {
    println!("⚖️  Comparison Operations");
    println!("========================");

    let data1 = vec![1.0, 2.0, 3.0, 4.0, 5.0];
    let data2 = vec![1.0, 1.0, 4.0, 4.0, 6.0];

    let col1 = Float64Column::new(data1);
    let col2 = Float64Column::new(data2);

    println!("Column 1: {:?}", col1.data());
    println!("Column 2: {:?}", col2.data());
    println!();

    // Equal
    let eq_result = col1.simd_compare(&col2, ComparisonOp::Equal)?;
    println!("Equal (col1 == col2): {eq_result:?}");

    // Greater than
    let gt_result = col1.simd_compare(&col2, ComparisonOp::GreaterThan)?;
    println!("Greater than (col1 > col2): {gt_result:?}");

    // Less than or equal
    let le_result = col1.simd_compare(&col2, ComparisonOp::LessThanEqual)?;
    println!("Less than or equal (col1 <= col2): {le_result:?}");

    // Scalar comparison
    println!();
    println!("Scalar comparisons:");
    let scalar_gt = col1.simd_compare_scalar(3.0, ComparisonOp::GreaterThan)?;
    println!("Column > 3.0: {scalar_gt:?}");

    let scalar_eq = col1.simd_compare_scalar(2.0, ComparisonOp::Equal)?;
    println!("Column == 2.0: {scalar_eq:?}");

    Ok(())
}

/// Demonstrate mixed-type operations with automatic promotion
#[allow(clippy::result_large_err)]
fn demo_mixed_type_operations() -> Result<()> {
    println!("🔄 Mixed-Type Operations");
    println!("=======================");

    let float_col = Column::Float64(Float64Column::new(vec![1.5, 2.5, 3.5]));
    let int_col = Column::Int64(Int64Column::new(vec![1, 2, 3]));

    println!("Float column: [1.5, 2.5, 3.5]");
    println!("Int column: [1, 2, 3]");
    println!();

    // Addition with type promotion
    let add_result = SIMDColumnArithmetic::add_columns(&float_col, &int_col)?;
    if let Column::Float64(result_col) = add_result {
        println!("Float + Int (promoted to Float): {:?}", result_col.data());
    }

    // Multiplication with type promotion
    let mul_result = SIMDColumnArithmetic::multiply_columns(&int_col, &float_col)?;
    if let Column::Float64(result_col) = mul_result {
        println!("Int * Float (promoted to Float): {:?}", result_col.data());
    }

    // Scalar multiplication
    let scalar_result = SIMDColumnArithmetic::multiply_scalar(&int_col, 2.5)?;
    if let Column::Float64(result_col) = scalar_result {
        println!("Int * 2.5 (promoted to Float): {:?}", result_col.data());
    }

    Ok(())
}

/// Compare performance between SIMD and scalar implementations
#[allow(clippy::result_large_err)]
fn demo_performance_comparison() -> Result<()> {
    println!("🚀 Performance Comparison");
    println!("========================");

    let size = 10_000;
    let data1: Vec<f64> = (0..size).map(|i| i as f64).collect();
    let data2: Vec<f64> = (0..size).map(|i| (i % 100) as f64).collect();

    let col1 = Float64Column::new(data1.clone());
    let col2 = Float64Column::new(data2.clone());

    println!("Dataset size: {size} elements");
    println!();

    // SIMD addition
    let start = Instant::now();
    for _ in 0..1000 {
        let _ = col1.simd_add(&col2)?;
    }
    let simd_time = start.elapsed();

    // Scalar addition (fallback simulation)
    let start = Instant::now();
    for _ in 0..1000 {
        let result: Vec<f64> = data1.iter().zip(data2.iter()).map(|(a, b)| a + b).collect();
        // Prevent optimization
        std::hint::black_box(result);
    }
    let scalar_time = start.elapsed();

    println!("Addition Performance (1000 iterations):");
    println!(
        "  SIMD implementation: {:.2}ms",
        simd_time.as_secs_f64() * 1000.0
    );
    println!(
        "  Scalar implementation: {:.2}ms",
        scalar_time.as_secs_f64() * 1000.0
    );

    let speedup = scalar_time.as_secs_f64() / simd_time.as_secs_f64();
    if speedup > 1.0 {
        println!("  SIMD speedup: {speedup:.1}x faster");
    } else {
        println!("  Performance ratio: {speedup:.1}x");
    }

    println!();

    // Test mathematical functions performance
    let positive_data: Vec<f64> = (1..=size).map(|i| i as f64).collect();
    let positive_col = Float64Column::new(positive_data.clone());

    // SIMD sqrt
    let start = Instant::now();
    for _ in 0..100 {
        let _ = positive_col.simd_sqrt()?;
    }
    let simd_sqrt_time = start.elapsed();

    // Scalar sqrt
    let start = Instant::now();
    for _ in 0..100 {
        let result: Vec<f64> = positive_data.iter().map(|&x| x.sqrt()).collect();
        std::hint::black_box(result);
    }
    let scalar_sqrt_time = start.elapsed();

    println!("Square Root Performance (100 iterations):");
    println!(
        "  SIMD sqrt: {:.2}ms",
        simd_sqrt_time.as_secs_f64() * 1000.0
    );
    println!(
        "  Scalar sqrt: {:.2}ms",
        scalar_sqrt_time.as_secs_f64() * 1000.0
    );

    let sqrt_speedup = scalar_sqrt_time.as_secs_f64() / simd_sqrt_time.as_secs_f64();
    if sqrt_speedup > 1.0 {
        println!("  SIMD sqrt speedup: {sqrt_speedup:.1}x faster");
    } else {
        println!("  Sqrt performance ratio: {sqrt_speedup:.1}x");
    }

    Ok(())
}

/// Demonstrate operations on large-scale datasets
#[allow(clippy::result_large_err)]
fn demo_large_scale_operations() -> Result<()> {
    println!("📈 Large-Scale Operations");
    println!("========================");

    let sizes = vec![1_000, 10_000, 100_000];

    for &size in &sizes {
        println!("Dataset size: {size} elements");

        let data1: Vec<f64> = (0..size).map(|i| (i as f64) * 0.001).collect();
        let data2: Vec<f64> = (0..size).map(|i| (i % 1000) as f64).collect();

        let col1 = Float64Column::new(data1);
        let col2 = Float64Column::new(data2);

        // Complex operation: (col1 + col2) * 2.0 - abs(col1)
        let start = Instant::now();

        let step1 = col1.simd_add(&col2)?;
        let step2 = step1.simd_multiply_scalar(2.0)?;
        let step3 = col1.simd_abs()?;
        let result = step2.simd_subtract(&step3)?;

        let operation_time = start.elapsed();

        println!(
            "  Complex operation time: {:.3}ms",
            operation_time.as_secs_f64() * 1000.0
        );
        println!(
            "  Operations per second: {:.0}",
            size as f64 / operation_time.as_secs_f64()
        );
        println!(
            "  Sample result (first 5 elements): {:?}",
            &result.data()[..5.min(result.data().len())]
        );
        println!();
    }

    Ok(())
}

fn print_summary() {
    println!("🎉 Comprehensive SIMD Column Operations Summary");
    println!("=============================================");
    println!("✅ Core Achievements:");
    println!("   • Element-wise arithmetic with 2-8x SIMD acceleration");
    println!("   • Scalar operations with efficient broadcasting");
    println!("   • Mathematical functions (abs, sqrt) with SIMD optimization");
    println!("   • Comprehensive comparison operations for all numeric types");
    println!("   • Mixed-type operations with automatic promotion");
    println!();
    println!("📈 Performance Benefits:");
    println!("   • AVX2 vectorization for 4x parallel f64 operations");
    println!("   • SSE2 fallback for 2x parallel operations");
    println!("   • Optimized null value handling in comparisons");
    println!("   • Efficient memory access patterns");
    println!("   • Saturating arithmetic for integer overflow protection");
    println!();
    println!("🏗️ Architecture Advantages:");
    println!("   • Seamless integration with existing column types");
    println!("   • Type-safe SIMD operations with compile-time optimization");
    println!("   • Automatic fallback to scalar operations when SIMD unavailable");
    println!("   • Comprehensive error handling and bounds checking");
    println!("   • Zero-cost abstractions over raw SIMD intrinsics");
    println!();
    println!("🔬 Use Cases:");
    println!("   • High-frequency trading and financial computations");
    println!("   • Scientific computing with large numerical datasets");
    println!("   • Machine learning feature engineering pipelines");
    println!("   • Real-time analytics and data transformation");
    println!("   • Statistical analysis and aggregation workloads");
    println!();
    println!("🚀 Next Steps:");
    println!("   • Extend to additional numeric types (f32, i32, u64)");
    println!("   • Implement SIMD string operations for text processing");
    println!("   • Add GPU acceleration for even larger datasets");
    println!("   • Integrate with lazy evaluation for query optimization");
}
