#![allow(
    clippy::assertions_on_constants,
    clippy::assertions_on_result_states,
    clippy::clone_on_copy,
    clippy::decimal_literal_representation,
    clippy::doc_markdown,
    clippy::empty_line_after_doc_comments,
    clippy::field_reassign_with_default,
    clippy::get_unwrap,
    clippy::identity_op,
    clippy::inconsistent_digit_grouping,
    clippy::indexing_slicing,
    clippy::integer_division,
    clippy::len_zero,
    clippy::let_underscore_must_use,
    clippy::manual_div_ceil,
    clippy::manual_let_else,
    clippy::manual_range_contains,
    clippy::modulo_arithmetic,
    clippy::needless_range_loop,
    clippy::non_ascii_literal,
    clippy::redundant_clone,
    clippy::shadow_reuse,
    clippy::shadow_same,
    clippy::shadow_unrelated,
    clippy::single_match_else,
    clippy::str_to_string,
    clippy::string_slice,
    clippy::tests_outside_test_module,
    clippy::too_many_lines,
    clippy::unnecessary_wraps,
    clippy::unseparated_literal_suffix,
    clippy::use_debug,
    clippy::useless_vec,
    clippy::wildcard_enum_match_arm,
    clippy::else_if_without_else,
    clippy::expect_used,
    clippy::missing_const_for_fn,
    clippy::similar_names,
    clippy::type_complexity,
    clippy::collapsible_else_if,
    clippy::doc_lazy_continuation,
    clippy::items_after_test_module,
    clippy::map_clone,
    clippy::multiple_unsafe_ops_per_block,
    clippy::unwrap_or_default,
    clippy::assign_op_pattern,
    clippy::needless_borrow,
    clippy::println_empty_string,
    clippy::unnecessary_cast,
    clippy::used_underscore_binding,
    clippy::create_dir,
    clippy::implicit_saturating_sub,
    clippy::exit,
    clippy::expect_fun_call,
    clippy::too_many_arguments,
    clippy::unnecessary_map_or,
    clippy::unwrap_used,
    dead_code,
    unused_imports,
    unused_variables,
    clippy::cloned_ref_to_slice_refs,
    clippy::neg_multiply,
    clippy::while_let_loop,
    clippy::bool_assert_comparison,
    clippy::excessive_precision,
    clippy::trivially_copy_pass_by_ref,
    clippy::op_ref,
    clippy::redundant_closure,
    clippy::unnecessary_lazy_evaluations,
    clippy::if_then_some_else_none,
    clippy::unnecessary_to_owned,
    clippy::single_component_path_imports,
)]
//! Liquid Networks Integration Tests
//!
//! Tests for Liquid Time-constant (LTC) and Closed-form Continuous-time (CfC)
//! neural networks with fixed-point arithmetic.
#![allow(unused_crate_dependencies)]
#![allow(
    clippy::assertions_on_result_states,
    clippy::doc_markdown,
    clippy::indexing_slicing,
    clippy::tests_outside_test_module,
    clippy::useless_vec,
)]

use ml::liquid::{
    cells::{CfCConfig, LTCConfig},
    ode_solvers::SolverType,
    ActivationType, FixedPoint, LiquidNetworkConfig, NetworkType,
};

#[tokio::test]
async fn test_fixed_point_arithmetic() {
    // Test basic fixed-point operations with Result handling
    let a = FixedPoint::from_f64(1.5);
    let b = FixedPoint::from_f64(2.5);

    let sum = (a + b).expect("addition should not overflow");
    assert!((sum.to_f64() - 4.0).abs() < 1e-6);

    let diff = (b - a).expect("subtraction should not overflow");
    assert!((diff.to_f64() - 1.0).abs() < 1e-6);

    let product = (a * b).expect("multiplication should not overflow");
    assert!((product.to_f64() - 3.75).abs() < 1e-6);

    let quotient = (b / a).expect("division should not overflow");
    assert!((quotient.to_f64() - (5.0 / 3.0)).abs() < 1e-6);

    // Test precision handling
    let precise = FixedPoint::from_f64(0.12345678);
    let recovered = precise.to_f64();
    assert!((recovered - 0.12345678).abs() < 1e-7);
}

#[tokio::test]
async fn test_fixed_point_special_values() {
    let zero = FixedPoint::zero();
    assert_eq!(zero.to_f64(), 0.0);

    let one = FixedPoint::one();
    assert!((one.to_f64() - 1.0).abs() < 1e-8);

    // Test is_finite
    assert!(zero.is_finite());
    assert!(one.is_finite());
    assert!(FixedPoint::from_f64(1000.0).is_finite());
}

#[tokio::test]
async fn test_fixed_point_overflow_handling() {
    let large = FixedPoint::from_f64(1e10);
    let result = large * large;

    // Should return an error for overflow
    assert!(result.is_err());
}

#[tokio::test]
async fn test_fixed_point_division_by_zero() {
    let a = FixedPoint::from_f64(1.0);
    let zero = FixedPoint::zero();

    let result = a / zero;
    assert!(result.is_err());
}

#[tokio::test]
async fn test_ltc_config_creation() {
    let config = LTCConfig {
        input_size: 10,
        hidden_size: 20,
        tau_min: FixedPoint::from_f64(0.1),
        tau_max: FixedPoint::from_f64(1.0),
        use_bias: true,
        solver_type: SolverType::Euler,
        activation: ActivationType::Tanh,
    };

    assert_eq!(config.input_size, 10);
    assert_eq!(config.hidden_size, 20);
    assert!(config.use_bias);
}

#[tokio::test]
async fn test_cfc_config_creation() {
    let config = CfCConfig {
        input_size: 15,
        hidden_size: 30,
        backbone_layers: vec![64, 32],
        mixed_memory: true,
        use_gate: true,
        solver_type: SolverType::RK4,
    };

    assert_eq!(config.input_size, 15);
    assert_eq!(config.hidden_size, 30);
    assert_eq!(config.backbone_layers.len(), 2);
    assert!(config.mixed_memory);
    assert!(config.use_gate);
}

#[tokio::test]
async fn test_liquid_network_config_creation() {
    let config = LiquidNetworkConfig {
        network_type: NetworkType::LTC,
        input_size: 64,
        output_size: 32,
        layer_configs: vec![],
        output_layer: ml::liquid::network::OutputLayerConfig {
            use_linear_output: true,
            output_activation: Some(ActivationType::Linear),
            dropout_rate: None,
        },
        default_dt: FixedPoint::from_f64(0.01),
        market_regime_adaptation: false,
    };

    assert_eq!(config.input_size, 64);
    assert_eq!(config.output_size, 32);
    assert!(matches!(config.network_type, NetworkType::LTC));
}

#[tokio::test]
async fn test_fixed_point_comparison() {
    let a = FixedPoint::from_f64(1.5);
    let b = FixedPoint::from_f64(2.5);
    let c = FixedPoint::from_f64(1.5);

    assert!(a < b);
    assert!(b > a);
    assert_eq!(a, c);
    assert_ne!(a, b);
}

#[tokio::test]
async fn test_fixed_point_ordering() {
    let mut values = vec![
        FixedPoint::from_f64(3.0),
        FixedPoint::from_f64(1.0),
        FixedPoint::from_f64(2.0),
    ];

    values.sort();

    assert_eq!(values[0].to_f64(), 1.0);
    assert_eq!(values[1].to_f64(), 2.0);
    assert_eq!(values[2].to_f64(), 3.0);
}

#[tokio::test]
async fn test_activation_types() {
    // Test that all activation types can be created
    let activations = vec![
        ActivationType::Tanh,
        ActivationType::Sigmoid,
        ActivationType::ReLU,
        ActivationType::LeakyReLU,
        ActivationType::Linear,
    ];

    for activation in activations {
        // Just verify they can be constructed
        let config = LTCConfig {
            input_size: 4,
            hidden_size: 8,
            tau_min: FixedPoint::from_f64(0.1),
            tau_max: FixedPoint::from_f64(1.0),
            use_bias: true,
            solver_type: SolverType::Euler,
            activation,
        };
        assert_eq!(config.input_size, 4);
    }
}

#[tokio::test]
async fn test_solver_types() {
    let solvers = vec![SolverType::Euler, SolverType::RK4, SolverType::Adaptive];

    for solver in solvers {
        let config = LTCConfig {
            input_size: 5,
            hidden_size: 10,
            tau_min: FixedPoint::from_f64(0.1),
            tau_max: FixedPoint::from_f64(1.0),
            use_bias: false,
            solver_type: solver,
            activation: ActivationType::Tanh,
        };
        assert_eq!(config.hidden_size, 10);
    }
}

#[tokio::test]
async fn test_network_types() {
    let types = vec![NetworkType::LTC, NetworkType::CfC, NetworkType::Mixed];

    for network_type in types {
        let config = LiquidNetworkConfig {
            network_type,
            input_size: 16,
            output_size: 8,
            layer_configs: vec![],
            output_layer: ml::liquid::network::OutputLayerConfig {
                use_linear_output: true,
                output_activation: Some(ActivationType::Linear),
                dropout_rate: None,
            },
            default_dt: FixedPoint::from_f64(0.01),
            market_regime_adaptation: false,
        };
        assert_eq!(config.input_size, 16);
    }
}

#[tokio::test]
async fn test_fixed_point_negative_values() {
    let neg = FixedPoint::from_f64(-5.5);
    let pos = FixedPoint::from_f64(3.0);

    let sum = (neg + pos).expect("addition should work");
    assert!((sum.to_f64() - (-2.5)).abs() < 1e-6);

    let product = (neg * pos).expect("multiplication should work");
    assert!((product.to_f64() - (-16.5)).abs() < 1e-6);
}

#[tokio::test]
async fn test_fixed_point_chain_operations() {
    let a = FixedPoint::from_f64(2.0);
    let b = FixedPoint::from_f64(3.0);
    let c = FixedPoint::from_f64(4.0);

    // Test: (a + b) * c
    let sum = (a + b).expect("addition should work");
    let result = (sum * c).expect("multiplication should work");
    assert!((result.to_f64() - 20.0).abs() < 1e-6);

    // Test: (a * b) + c
    let product = (a * b).expect("multiplication should work");
    let result2 = (product + c).expect("addition should work");
    assert!((result2.to_f64() - 10.0).abs() < 1e-6);
}

#[tokio::test]
async fn test_config_with_varying_sizes() {
    let sizes = vec![(2, 4), (10, 20), (50, 100), (128, 256)];

    for (input_size, hidden_size) in sizes {
        let config = LTCConfig {
            input_size,
            hidden_size,
            tau_min: FixedPoint::from_f64(0.1),
            tau_max: FixedPoint::from_f64(1.0),
            use_bias: true,
            solver_type: SolverType::Euler,
            activation: ActivationType::Tanh,
        };

        assert_eq!(config.input_size, input_size);
        assert_eq!(config.hidden_size, hidden_size);
    }
}

#[tokio::test]
async fn test_time_constant_ranges() {
    let tau_ranges = vec![(0.01, 0.1), (0.1, 1.0), (1.0, 10.0)];

    for (tau_min, tau_max) in tau_ranges {
        let config = LTCConfig {
            input_size: 8,
            hidden_size: 16,
            tau_min: FixedPoint::from_f64(tau_min),
            tau_max: FixedPoint::from_f64(tau_max),
            use_bias: true,
            solver_type: SolverType::Euler,
            activation: ActivationType::Tanh,
        };

        assert!((config.tau_min.to_f64() - tau_min).abs() < 1e-6);
        assert!((config.tau_max.to_f64() - tau_max).abs() < 1e-6);
        assert!(config.tau_min < config.tau_max);
    }
}

#[tokio::test]
async fn test_cfc_backbone_configurations() {
    let backbone_configs = vec![vec![32], vec![64, 32], vec![128, 64, 32]];

    for backbone in backbone_configs {
        let expected_len = backbone.len();
        let config = CfCConfig {
            input_size: 16,
            hidden_size: 32,
            backbone_layers: backbone.clone(),
            mixed_memory: true,
            use_gate: true,
            solver_type: SolverType::RK4,
        };

        assert_eq!(config.backbone_layers.len(), expected_len);
        assert_eq!(config.backbone_layers, backbone);
    }
}

#[tokio::test]
async fn test_fixed_point_precision_limits() {
    // Test values near precision limits
    let small = FixedPoint::from_f64(1e-7);
    assert!(small.to_f64() > 0.0);
    assert!(small.to_f64() < 1e-6);

    let large = FixedPoint::from_f64(1e6);
    assert!(large.to_f64() > 999999.0);
    assert!(large.to_f64() < 1000001.0);
}

#[tokio::test]
async fn test_dt_values() {
    let dt_values = vec![0.001, 0.01, 0.05, 0.1];

    for dt in dt_values {
        let config = LiquidNetworkConfig {
            network_type: NetworkType::LTC,
            input_size: 10,
            output_size: 5,
            layer_configs: vec![],
            output_layer: ml::liquid::network::OutputLayerConfig {
                use_linear_output: true,
                output_activation: Some(ActivationType::Linear),
                dropout_rate: None,
            },
            default_dt: FixedPoint::from_f64(dt),
            market_regime_adaptation: false,
        };

        assert!((config.default_dt.to_f64() - dt).abs() < 1e-8);
    }
}
