// tests/tables_data/handlers/put_table_data_test4.rs


#[derive(Clone)]
struct ComprehensiveIntegerTestContext {
    pool: PgPool,
    profile_name: String,
    mixed_integer_table: String,
    bigint_only_table: String,
    integer_only_table: String,
    indexer_tx: mpsc::Sender<IndexCommand>,
}

#[derive(Clone)]
struct AdvancedDecimalTestContext {
    pool: PgPool,
    profile_name: String,
    table_name: String,
    indexer_tx: mpsc::Sender<IndexCommand>,
}

#[derive(Clone)]
struct PerformanceTestContext {
    pool: PgPool,
    profile_name: String,
    stress_table: String,
    indexer_tx: mpsc::Sender<IndexCommand>,
}

// ========================================================================
// TABLE CREATION HELPERS FOR COMPREHENSIVE TESTING
// ========================================================================

async fn create_comprehensive_integer_tables(
    pool: &PgPool,
    profile_name: &str,
) -> Result<ComprehensiveIntegerTestContext, tonic::Status> {
    let unique_id = generate_unique_id();
    let mixed_table = format!("comprehensive_mixed_table_{}", unique_id);
    let bigint_table = format!("comprehensive_bigint_table_{}", unique_id);
    let integer_table = format!("comprehensive_integer_table_{}", unique_id);

    // Table with both INTEGER and BIGINT columns for comprehensive testing
    let mixed_def = PostTableDefinitionRequest {
        profile_name: profile_name.into(),
        table_name: mixed_table.clone(),
        columns: vec![
            TableColumnDefinition { name: "name".into(), field_type: "text".into() },
            TableColumnDefinition { name: "small_int".into(), field_type: "integer".into() },
            TableColumnDefinition { name: "big_int".into(), field_type: "biginteger".into() },
            TableColumnDefinition { name: "another_int".into(), field_type: "int".into() },
            TableColumnDefinition { name: "another_bigint".into(), field_type: "bigint".into() },
            TableColumnDefinition { name: "nullable_int".into(), field_type: "integer".into() },
            TableColumnDefinition { name: "nullable_bigint".into(), field_type: "biginteger".into() },
        ],
        indexes: vec![],
        links: vec![],
    };
    post_table_definition(pool, mixed_def).await?;

    // Table with only BIGINT columns for edge case testing
    let bigint_def = PostTableDefinitionRequest {
        profile_name: profile_name.into(),
        table_name: bigint_table.clone(),
        columns: vec![
            TableColumnDefinition { name: "name".into(), field_type: "text".into() },
            TableColumnDefinition { name: "value1".into(), field_type: "biginteger".into() },
            TableColumnDefinition { name: "value2".into(), field_type: "bigint".into() },
            TableColumnDefinition { name: "extreme_value".into(), field_type: "biginteger".into() },
        ],
        indexes: vec![],
        links: vec![],
    };
    post_table_definition(pool, bigint_def).await?;

    // Table with only INTEGER columns for boundary testing
    let integer_def = PostTableDefinitionRequest {
        profile_name: profile_name.into(),
        table_name: integer_table.clone(),
        columns: vec![
            TableColumnDefinition { name: "name".into(), field_type: "text".into() },
            TableColumnDefinition { name: "value1".into(), field_type: "integer".into() },
            TableColumnDefinition { name: "value2".into(), field_type: "int".into() },
            TableColumnDefinition { name: "boundary_test".into(), field_type: "integer".into() },
        ],
        indexes: vec![],
        links: vec![],
    };
    post_table_definition(pool, integer_def).await?;

    let (tx, mut rx) = mpsc::channel(100);
    tokio::spawn(async move { while rx.recv().await.is_some() {} });

    Ok(ComprehensiveIntegerTestContext {
        pool: pool.clone(),
        profile_name: profile_name.to_string(),
        mixed_integer_table: mixed_table,
        bigint_only_table: bigint_table,
        integer_only_table: integer_table,
        indexer_tx: tx,
    })
}

async fn create_advanced_decimal_table(
    pool: &PgPool,
    table_name: &str,
    profile_name: &str,
) -> Result<(), tonic::Status> {
    let table_def_request = PostTableDefinitionRequest {
        profile_name: profile_name.into(),
        table_name: table_name.into(),
        columns: vec![
            TableColumnDefinition { name: "product_name".into(), field_type: "text".into() },
            TableColumnDefinition { name: "price".into(), field_type: "decimal(19, 4)".into() },
            TableColumnDefinition { name: "rate".into(), field_type: "decimal(10, 5)".into() },
            TableColumnDefinition { name: "discount".into(), field_type: "decimal(5, 3)".into() },
            TableColumnDefinition { name: "ultra_precise".into(), field_type: "decimal(28, 10)".into() },
            TableColumnDefinition { name: "percentage".into(), field_type: "decimal(5, 4)".into() },
        ],
        indexes: vec![],
        links: vec![],
    };

    post_table_definition(pool, table_def_request).await?;
    Ok(())
}

async fn create_performance_stress_table(
    pool: &PgPool,
    table_name: &str,
    profile_name: &str,
) -> Result<(), tonic::Status> {
    let table_def_request = PostTableDefinitionRequest {
        profile_name: profile_name.into(),
        table_name: table_name.into(),
        columns: vec![
            TableColumnDefinition { name: "test_name".into(), field_type: "text".into() },
            TableColumnDefinition { name: "int_val1".into(), field_type: "integer".into() },
            TableColumnDefinition { name: "int_val2".into(), field_type: "integer".into() },
            TableColumnDefinition { name: "bigint_val1".into(), field_type: "biginteger".into() },
            TableColumnDefinition { name: "bigint_val2".into(), field_type: "biginteger".into() },
            TableColumnDefinition { name: "decimal_val".into(), field_type: "decimal(10, 2)".into() },
            TableColumnDefinition { name: "bool_val".into(), field_type: "boolean".into() },
            TableColumnDefinition { name: "timestamp_val".into(), field_type: "timestamptz".into() },
        ],
        indexes: vec![],
        links: vec![],
    };

    post_table_definition(pool, table_def_request).await?;
    Ok(())
}

// ========================================================================
// FIXTURES
// ========================================================================

#[fixture]
async fn comprehensive_integer_test_context() -> ComprehensiveIntegerTestContext {
    let pool = setup_test_db().await;
    let unique_id = generate_unique_id();
    let profile_name = format!("comp_int_profile_{}", unique_id);

    create_comprehensive_integer_tables(&pool, &profile_name).await
        .expect("Failed to create comprehensive integer test tables")
}

#[fixture]
async fn advanced_decimal_test_context() -> AdvancedDecimalTestContext {
    let pool = setup_test_db().await;
    let unique_id = generate_unique_id();
    let profile_name = format!("adv_decimal_profile_{}", unique_id);
    let table_name = format!("advanced_decimals_{}", unique_id);

    create_advanced_decimal_table(&pool, &table_name, &profile_name).await
        .expect("Failed to create advanced decimal test table");

    let (tx, mut rx) = mpsc::channel(100);
    tokio::spawn(async move { while rx.recv().await.is_some() {} });

    AdvancedDecimalTestContext { pool, profile_name, table_name, indexer_tx: tx }
}

#[fixture]
async fn performance_test_context() -> PerformanceTestContext {
    let pool = setup_test_db().await;
    let unique_id = generate_unique_id();
    let profile_name = format!("perf_profile_{}", unique_id);
    let stress_table = format!("stress_table_{}", unique_id);

    create_performance_stress_table(&pool, &stress_table, &profile_name).await
        .expect("Failed to create performance stress test table");

    let (tx, mut rx) = mpsc::channel(100);
    tokio::spawn(async move { while rx.recv().await.is_some() {} });

    PerformanceTestContext { pool, profile_name, stress_table, indexer_tx: tx }
}

// ========================================================================
// HELPER FUNCTIONS FOR CREATING INITIAL RECORDS
// ========================================================================

async fn create_initial_comprehensive_integer_record(
    context: &ComprehensiveIntegerTestContext,
    table_name: &str
) -> i64 {
    let mut initial_data = HashMap::new();
    initial_data.insert("name".to_string(), string_to_proto_value("Initial Record"));

    match table_name {
        table if table.contains("mixed") => {
            initial_data.insert("small_int".to_string(), Value { kind: Some(Kind::NumberValue(100.0)) });
            initial_data.insert("big_int".to_string(), Value { kind: Some(Kind::NumberValue(1000000000000.0)) });
            initial_data.insert("another_int".to_string(), Value { kind: Some(Kind::NumberValue(200.0)) });
            initial_data.insert("another_bigint".to_string(), Value { kind: Some(Kind::NumberValue(2000000000000.0)) });
            initial_data.insert("nullable_int".to_string(), Value { kind: Some(Kind::NumberValue(300.0)) });
            initial_data.insert("nullable_bigint".to_string(), Value { kind: Some(Kind::NumberValue(3000000000000.0)) });
        },
        table if table.contains("bigint") => {
            initial_data.insert("value1".to_string(), Value { kind: Some(Kind::NumberValue(1000000000000.0)) });
            initial_data.insert("value2".to_string(), Value { kind: Some(Kind::NumberValue(2000000000000.0)) });
            initial_data.insert("extreme_value".to_string(), Value { kind: Some(Kind::NumberValue(9223372036854774784.0)) });
        },
        table if table.contains("integer") => {
            initial_data.insert("value1".to_string(), Value { kind: Some(Kind::NumberValue(100.0)) });
            initial_data.insert("value2".to_string(), Value { kind: Some(Kind::NumberValue(200.0)) });
            initial_data.insert("boundary_test".to_string(), Value { kind: Some(Kind::NumberValue(300.0)) });
        },
        _ => {}
    }

    let request = PostTableDataRequest {
        profile_name: context.profile_name.clone(),
        table_name: table_name.to_string(),
        data: initial_data,
    };
    let response = post_table_data(&context.pool, request, &context.indexer_tx)
        .await
        .expect("Setup: Failed to create initial integer record");
    response.inserted_id
}

async fn create_initial_advanced_decimal_record(context: &AdvancedDecimalTestContext) -> i64 {
    let mut initial_data = HashMap::new();
    initial_data.insert("product_name".to_string(), string_to_proto_value("Initial Product"));
    initial_data.insert("price".to_string(), string_to_proto_value("100.0000"));
    initial_data.insert("rate".to_string(), string_to_proto_value("1.00000"));
    initial_data.insert("discount".to_string(), string_to_proto_value("0.100"));
    initial_data.insert("ultra_precise".to_string(), string_to_proto_value("123.4567890123"));
    initial_data.insert("percentage".to_string(), string_to_proto_value("0.9999"));

    let request = PostTableDataRequest {
        profile_name: context.profile_name.clone(),
        table_name: context.table_name.clone(),
        data: initial_data,
    };
    let response = post_table_data(&context.pool, request, &context.indexer_tx)
        .await
        .expect("Setup: Failed to create initial decimal record");
    response.inserted_id
}

async fn create_initial_performance_record(context: &PerformanceTestContext) -> i64 {
    let mut initial_data = HashMap::new();
    initial_data.insert("test_name".to_string(), string_to_proto_value("Initial Performance Test"));
    initial_data.insert("int_val1".to_string(), Value { kind: Some(Kind::NumberValue(1.0)) });
    initial_data.insert("int_val2".to_string(), Value { kind: Some(Kind::NumberValue(2.0)) });
    initial_data.insert("bigint_val1".to_string(), Value { kind: Some(Kind::NumberValue(1000000000000.0)) });
    initial_data.insert("bigint_val2".to_string(), Value { kind: Some(Kind::NumberValue(2000000000000.0)) });
    initial_data.insert("decimal_val".to_string(), string_to_proto_value("123.45"));
    initial_data.insert("bool_val".to_string(), Value { kind: Some(Kind::BoolValue(false)) });
    initial_data.insert("timestamp_val".to_string(), string_to_proto_value("2024-01-01T00:00:00Z"));

    let request = PostTableDataRequest {
        profile_name: context.profile_name.clone(),
        table_name: context.stress_table.clone(),
        data: initial_data,
    };
    let response = post_table_data(&context.pool, request, &context.indexer_tx)
        .await
        .expect("Setup: Failed to create initial performance record");
    response.inserted_id
}

// ========================================================================
// BIGINT SUCCESSFUL ROUNDTRIP VALUE TESTS
// ========================================================================

#[rstest]
#[tokio::test]
async fn test_update_bigint_successful_roundtrip_values(
    #[future] comprehensive_integer_test_context: ComprehensiveIntegerTestContext,
) {
    let context = comprehensive_integer_test_context.await;
    let record_id = create_initial_comprehensive_integer_record(&context, &context.bigint_only_table).await;

    // Values that SHOULD successfully round-trip and be accepted for updates
    let successful_values = vec![
        (9223372036854775808.0, "Exactly i64::MAX as f64 (legitimate value)"),
        (-9223372036854775808.0, "Exactly i64::MIN as f64 (legitimate value)"),
        (9223372036854774784.0, "Large but precisely representable in f64"),
        (-9223372036854774784.0, "Large negative but precisely representable in f64"),
        (0.0, "Zero"),
        (1.0, "One"),
        (-1.0, "Negative one"),
        (2147483647.0, "i32::MAX as f64"),
        (-2147483648.0, "i32::MIN as f64"),
        (4611686018427387904.0, "i64::MAX / 2"),
        (-4611686018427387904.0, "i64::MIN / 2"),
        (1000000000000.0, "One trillion"),
        (-1000000000000.0, "Negative one trillion"),
    ];

    for (value, description) in successful_values {
        let mut update_data = HashMap::new();
        update_data.insert("name".to_string(), string_to_proto_value(&format!("Roundtrip test: {}", description)));
        update_data.insert("value1".to_string(), Value { kind: Some(Kind::NumberValue(value)) });
        update_data.insert("extreme_value".to_string(), Value { kind: Some(Kind::NumberValue(value)) });

        let request = PutTableDataRequest {
            profile_name: context.profile_name.clone(),
            table_name: context.bigint_only_table.clone(),
            id: record_id,
            data: update_data,
        };

        let result = put_table_data(&context.pool, request, &context.indexer_tx).await;
        assert!(result.is_ok(), "Should have succeeded for legitimate i64 update value {}: {}", value, description);

        // Verify it was stored correctly
        if let Ok(response) = result {
            let query = format!(
                r#"SELECT value1, extreme_value FROM "{}"."{}" WHERE id = $1"#,
                context.profile_name, context.bigint_only_table
            );
            let row = sqlx::query(&query)
                .bind(record_id)
                .fetch_one(&context.pool)
                .await
                .unwrap();

            let stored_value1: i64 = row.get("value1");
            let stored_extreme_value: i64 = row.get("extreme_value");
            
            assert_eq!(stored_value1, value as i64, "Value1 should match for {}", description);
            assert_eq!(stored_extreme_value, value as i64, "Extreme value should match for {}", description);
        }
    }
}

#[rstest]
#[tokio::test]
async fn test_update_bigint_overflow_rejection_comprehensive(
    #[future] comprehensive_integer_test_context: ComprehensiveIntegerTestContext,
) {
    let context = comprehensive_integer_test_context.await;
    let record_id = create_initial_comprehensive_integer_record(&context, &context.bigint_only_table).await;

    // Values that should be rejected for BIGINT columns due to precision loss or overflow
    let overflow_values = vec![
        (f64::INFINITY, "Positive infinity"),
        (f64::NEG_INFINITY, "Negative infinity"),
        (1e20, "Very large number (100,000,000,000,000,000,000)"),
        (-1e20, "Very large negative number"),
        (1e25, "Extremely large number"),
        (-1e25, "Extremely large negative number"),
        (f64::MAX, "f64::MAX"),
        (f64::MIN, "f64::MIN"),
        (f64::NAN, "NaN"),
    ];

    for (value, description) in overflow_values {
        let mut update_data = HashMap::new();
        update_data.insert("name".to_string(), string_to_proto_value(&format!("i64 Overflow update test: {}", description)));
        update_data.insert("extreme_value".to_string(), Value { kind: Some(Kind::NumberValue(value)) });

        let request = PutTableDataRequest {
            profile_name: context.profile_name.clone(),
            table_name: context.bigint_only_table.clone(),
            id: record_id,
            data: update_data,
        };

        let result = put_table_data(&context.pool, request, &context.indexer_tx).await;

        assert!(result.is_err(), "Should have failed for i64 overflow update value {}: {}", value, description);

        if let Err(err) = result {
            assert_eq!(err.code(), tonic::Code::InvalidArgument);
            let message = err.message();
            assert!(
                message.contains("Integer value out of range for BIGINT column") ||
                message.contains("Expected integer for column") ||
                message.contains("but got a float") ||
                message.contains("Invalid number"),
                "Unexpected error message for {}: {}",
                description,
                message
            );
        }
    }
}

// ========================================================================
// WRONG TYPE FOR MIXED INTEGER COLUMNS TESTS
// ========================================================================

#[rstest]
#[tokio::test]
async fn test_update_wrong_type_for_mixed_integer_columns(
    #[future] comprehensive_integer_test_context: ComprehensiveIntegerTestContext,
) {
    let context = comprehensive_integer_test_context.await;
    let record_id = create_initial_comprehensive_integer_record(&context, &context.mixed_integer_table).await;

    // Try to put i64 values into i32 columns (should fail)
    let wrong_type_tests = vec![
        ("small_int", 3000000000.0, "3 billion in i32 column"),
        ("another_int", -3000000000.0, "negative 3 billion in i32 column"),
        ("nullable_int", 2147483648.0, "i32::MAX + 1 in i32 column"),
        ("small_int", 9223372036854775807.0, "i64::MAX in i32 column"),
    ];

    for (column_name, value, description) in wrong_type_tests {
        let mut update_data = HashMap::new();
        update_data.insert("name".to_string(), string_to_proto_value(&format!("Wrong type test: {}", description)));
        update_data.insert(column_name.to_string(), Value { kind: Some(Kind::NumberValue(value)) });

        let request = PutTableDataRequest {
            profile_name: context.profile_name.clone(),
            table_name: context.mixed_integer_table.clone(),
            id: record_id,
            data: update_data,
        };

        let result = put_table_data(&context.pool, request, &context.indexer_tx).await;
        assert!(result.is_err(), "Should fail when putting i64 value {} in i32 column {}", value, column_name);

        if let Err(err) = result {
            assert_eq!(err.code(), tonic::Code::InvalidArgument);
            assert!(err.message().contains("Integer value out of range for INTEGER column"));
        }
    }

    // Try fractional values in integer columns (should fail)
    let fractional_tests = vec![
        ("small_int", 42.5, "fractional in i32 column"),
        ("big_int", 1000000000000.1, "fractional in i64 column"),
        ("another_int", -42.9, "negative fractional in i32 column"),
        ("another_bigint", -1000000000000.9, "negative fractional in i64 column"),
    ];

    for (column_name, value, description) in fractional_tests {
        let mut update_data = HashMap::new();
        update_data.insert("name".to_string(), string_to_proto_value(&format!("Fractional test: {}", description)));
        update_data.insert(column_name.to_string(), Value { kind: Some(Kind::NumberValue(value)) });

        let request = PutTableDataRequest {
            profile_name: context.profile_name.clone(),
            table_name: context.mixed_integer_table.clone(),
            id: record_id,
            data: update_data,
        };

        let result = put_table_data(&context.pool, request, &context.indexer_tx).await;
        assert!(result.is_err(), "Should fail for fractional value {} in column {}", value, column_name);

        if let Err(err) = result {
            assert_eq!(err.code(), tonic::Code::InvalidArgument);
            assert!(err.message().contains("Expected integer for column") && err.message().contains("but got a float"));
        }
    }
}

// ========================================================================
// CONCURRENT MIXED INTEGER UPDATES TESTS
// ========================================================================

#[rstest]
#[tokio::test]
async fn test_update_concurrent_mixed_integer_updates(
    #[future] comprehensive_integer_test_context: ComprehensiveIntegerTestContext,
) {
    let context = comprehensive_integer_test_context.await;
    // Create multiple records for concurrent updating
    let mut record_ids = Vec::new();
    for i in 0..10 {
        let record_id = create_initial_comprehensive_integer_record(&context, &context.mixed_integer_table).await;
        record_ids.push(record_id);
    }
    // Test concurrent updates with different integer types
    let tasks: Vec<_> = record_ids.into_iter().enumerate().map(|(i, record_id)| {
        let context = context.clone();
        tokio::spawn(async move {
            let mut update_data = HashMap::new();
            update_data.insert("name".to_string(), string_to_proto_value(&format!("Concurrent update test {}", i)));
            update_data.insert("small_int".to_string(), Value { kind: Some(Kind::NumberValue((i * 1000) as f64)) });
            update_data.insert("big_int".to_string(), Value { kind: Some(Kind::NumberValue((i as i64 * 1000000000000) as f64)) });
            // Fix: Cast i to i32 first, then multiply by negative number
            update_data.insert("another_int".to_string(), Value { kind: Some(Kind::NumberValue(((i as i32) * -100) as f64)) });
            update_data.insert("another_bigint".to_string(), Value { kind: Some(Kind::NumberValue((i as i64 * -1000000000000) as f64)) });
            // Alternate between null and values for nullable columns
            if i % 2 == 0 {
                update_data.insert("nullable_int".to_string(), Value { kind: Some(Kind::NumberValue((i * 42) as f64)) });
                update_data.insert("nullable_bigint".to_string(), Value { kind: Some(Kind::NullValue(0)) });
            } else {
                update_data.insert("nullable_int".to_string(), Value { kind: Some(Kind::NullValue(0)) });
                update_data.insert("nullable_bigint".to_string(), Value { kind: Some(Kind::NumberValue((i as i64 * 9999999999) as f64)) });
            }
            let request = PutTableDataRequest {
                profile_name: context.profile_name.clone(),
                table_name: context.mixed_integer_table.clone(),
                id: record_id,
                data: update_data,
            };
            put_table_data(&context.pool, request, &context.indexer_tx).await
        })
    }).collect();
    // Wait for all tasks to complete
    let results = futures::future::join_all(tasks).await;
    // All should succeed
    for (i, result) in results.into_iter().enumerate() {
        let task_result = result.expect("Task should not panic");
        assert!(task_result.is_ok(), "Concurrent integer update {} should succeed", i);
    }
    // Verify all records were updated correctly
    let query = format!(
        r#"SELECT COUNT(*) FROM "{}"."{}" WHERE name LIKE 'Concurrent update test%'"#,
        context.profile_name, context.mixed_integer_table
    );
    let count: i64 = sqlx::query_scalar(&query)
        .fetch_one(&context.pool)
        .await
        .unwrap();
    assert_eq!(count, 10);
}

// ========================================================================
// ADVANCED DECIMAL PRECISION EDGE CASES
// ========================================================================

#[rstest]
#[tokio::test]
async fn test_update_ultra_high_precision_decimals(
    #[future] advanced_decimal_test_context: AdvancedDecimalTestContext,
) {
    let context = advanced_decimal_test_context.await;
    let record_id = create_initial_advanced_decimal_record(&context).await;

    let ultra_precision_tests = vec![
        ("ultra_precise", "123456789.1234567890", dec!(123456789.1234567890)),
        ("ultra_precise", "-999999999.9999999999", dec!(-999999999.9999999999)),
        ("ultra_precise", "0.0000000001", dec!(0.0000000001)),
        ("percentage", "0.9999", dec!(0.9999)), // decimal(5,4) - 0.9999 is max
        ("percentage", "0.0001", dec!(0.0001)), // decimal(5,4) - minimum precision
    ];

    for (field, value_str, expected_decimal) in ultra_precision_tests {
        let mut update_data = HashMap::new();
        update_data.insert("product_name".to_string(), string_to_proto_value("Ultra precision test"));
        update_data.insert(field.to_string(), string_to_proto_value(value_str));

        let request = PutTableDataRequest {
            profile_name: context.profile_name.clone(),
            table_name: context.table_name.clone(),
            id: record_id,
            data: update_data,
        };

        let response = put_table_data(&context.pool, request, &context.indexer_tx)
            .await
            .unwrap();
        assert!(response.success);

        // Verify ultra high precision was preserved
        let query = format!(
            r#"SELECT {} FROM "{}"."{}" WHERE id = $1"#,
            field, context.profile_name, context.table_name
        );
        let stored_value: rust_decimal::Decimal = sqlx::query_scalar(&query)
            .bind(record_id)
            .fetch_one(&context.pool)
            .await
            .unwrap();

        assert_eq!(stored_value, expected_decimal, "Ultra precision mismatch for field {}", field);
    }
}

#[rstest]
#[tokio::test]
async fn test_update_decimal_edge_case_rounding(
    #[future] advanced_decimal_test_context: AdvancedDecimalTestContext,
) {
    let context = advanced_decimal_test_context.await;
    let record_id = create_initial_advanced_decimal_record(&context).await;

    // Test edge cases where rounding behavior is critical
    let edge_rounding_tests = vec![
        ("price", "12345.99995", dec!(12346.0000)), // Should round up at 5
        ("rate", "1.999995", dec!(2.00000)), // Should round up
        ("discount", "0.9995", dec!(1.000)), // Should round up to 1.000
        ("percentage", "0.99995", dec!(1.0000)), // decimal(5,4) rounds to 1.0000
        ("ultra_precise", "1.99999999995", dec!(2.0000000000)), // Ultra precision rounding
    ];

    for (field, input_value, expected_rounded) in edge_rounding_tests {
        let mut update_data = HashMap::new();
        update_data.insert("product_name".to_string(), string_to_proto_value("Edge rounding test"));
        update_data.insert(field.to_string(), string_to_proto_value(input_value));

        let request = PutTableDataRequest {
            profile_name: context.profile_name.clone(),
            table_name: context.table_name.clone(),
            id: record_id,
            data: update_data,
        };

        let response = put_table_data(&context.pool, request, &context.indexer_tx)
            .await
            .unwrap();
        assert!(response.success);

        // Verify edge case rounding was applied correctly
        let query = format!(
            r#"SELECT {} FROM "{}"."{}" WHERE id = $1"#,
            field, context.profile_name, context.table_name
        );
        let stored_value: rust_decimal::Decimal = sqlx::query_scalar(&query)
            .bind(record_id)
            .fetch_one(&context.pool)
            .await
            .unwrap();

        assert_eq!(stored_value, expected_rounded, "Edge rounding mismatch for field {}", field);
    }
}

// ========================================================================
// PERFORMANCE AND STRESS TESTS
// ========================================================================

#[rstest]
#[tokio::test]
async fn test_update_rapid_integer_updates_stress(
    #[future] performance_test_context: PerformanceTestContext,
) {
    let context = performance_test_context.await;

    // Create initial records for stress testing
    let mut record_ids = Vec::new();
    for i in 0..100 {
        let record_id = create_initial_performance_record(&context).await;
        record_ids.push(record_id);
    }

    // Rapid sequential updates with alternating integer types and complex data
    let start = std::time::Instant::now();

    for (i, record_id) in record_ids.iter().enumerate() {
        let mut update_data = HashMap::new();
        update_data.insert("test_name".to_string(), string_to_proto_value(&format!("Stress update test {}", i)));

        // Alternate between different boundary values for stress testing
        let small_val = match i % 4 {
            0 => 2147483647.0,  // i32::MAX
            1 => -2147483648.0, // i32::MIN
            2 => 0.0,
            _ => (i as f64) * 1000.0,
        };

        let big_val = match i % 4 {
            0 => 9223372036854774784.0,  // Near i64::MAX
            1 => -9223372036854774784.0, // Near i64::MIN
            2 => 0.0,
            _ => (i as f64) * 1000000000000.0,
        };

        update_data.insert("int_val1".to_string(), Value { kind: Some(Kind::NumberValue(small_val)) });
        update_data.insert("int_val2".to_string(), Value { kind: Some(Kind::NumberValue(small_val)) });
        update_data.insert("bigint_val1".to_string(), Value { kind: Some(Kind::NumberValue(big_val)) });
        update_data.insert("bigint_val2".to_string(), Value { kind: Some(Kind::NumberValue(big_val)) });
        
        // Add some decimal and other type updates for comprehensive stress test
        update_data.insert("decimal_val".to_string(), string_to_proto_value(&format!("{}.{:02}", i * 10, i % 100)));
        update_data.insert("bool_val".to_string(), Value { kind: Some(Kind::BoolValue(i % 2 == 0)) });
        update_data.insert("timestamp_val".to_string(), string_to_proto_value(&format!("2024-01-{:02}T{:02}:00:00Z", (i % 28) + 1, i % 24)));

        let request = PutTableDataRequest {
            profile_name: context.profile_name.clone(),
            table_name: context.stress_table.clone(),
            id: *record_id,
            data: update_data,
        };

        let result = put_table_data(&context.pool, request, &context.indexer_tx).await;
        assert!(result.is_ok(), "Rapid stress update {} should succeed", i);
    }

    let duration = start.elapsed();
    println!("100 mixed data type stress updates took: {:?}", duration);

    // Should complete in reasonable time (adjust threshold as needed)
    assert!(duration.as_secs() < 15, "Stress test took too long: {:?}", duration);

    // Verify all records were updated correctly
    let query = format!(
        r#"SELECT COUNT(*) FROM "{}"."{}" WHERE test_name LIKE 'Stress update test%'"#,
        context.profile_name, context.stress_table
    );

    let count: i64 = sqlx::query_scalar(&query)
        .fetch_one(&context.pool)
        .await
        .unwrap();
    assert_eq!(count, 100);
}

#[rstest]
#[tokio::test]
async fn test_update_concurrent_stress_mixed_data_types(
    #[future] performance_test_context: PerformanceTestContext,
) {
    let context = performance_test_context.await;

    // Create initial records
    let mut record_ids = Vec::new();
    for i in 0..20 {
        let record_id = create_initial_performance_record(&context).await;
        record_ids.push(record_id);
    }

    // Concurrent stress test with mixed data types
    let tasks: Vec<_> = record_ids.into_iter().enumerate().map(|(i, record_id)| {
        let context = context.clone();

        tokio::spawn(async move {
            let mut update_data = HashMap::new();
            update_data.insert("test_name".to_string(), string_to_proto_value(&format!("Concurrent stress {}", i)));
            
            // Use complex values that stress different validation paths
            let complex_int = match i % 3 {
                0 => 2147483647.0 - (i as f64), // Near i32::MAX
                1 => -2147483648.0 + (i as f64), // Near i32::MIN
                _ => (i as f64) * 12345.0,
            };

            let complex_bigint = match i % 3 {
                0 => 9223372036854774784.0 - (i as f64 * 1000000000.0),
                1 => -9223372036854774784.0 + (i as f64 * 1000000000.0),
                _ => (i as f64) * 987654321012345.0,
            };

            update_data.insert("int_val1".to_string(), Value { kind: Some(Kind::NumberValue(complex_int)) });
            update_data.insert("int_val2".to_string(), Value { kind: Some(Kind::NumberValue(complex_int)) });
            update_data.insert("bigint_val1".to_string(), Value { kind: Some(Kind::NumberValue(complex_bigint)) });
            update_data.insert("bigint_val2".to_string(), Value { kind: Some(Kind::NumberValue(complex_bigint)) });
            update_data.insert("decimal_val".to_string(), string_to_proto_value(&format!("{}.{:02}", i * 33, (i * 7) % 100)));
            update_data.insert("bool_val".to_string(), Value { kind: Some(Kind::BoolValue((i * 3) % 2 == 0)) });

            let request = PutTableDataRequest {
                profile_name: context.profile_name.clone(),
                table_name: context.stress_table.clone(),
                id: record_id,
                data: update_data,
            };

            put_table_data(&context.pool, request, &context.indexer_tx).await
        })
    }).collect();

    // Wait for all concurrent updates to complete
    let results = futures::future::join_all(tasks).await;

    // All should succeed
    for (i, result) in results.into_iter().enumerate() {
        let task_result = result.expect("Task should not panic");
        assert!(task_result.is_ok(), "Concurrent stress update {} should succeed", i);
    }

    // Verify all records were updated
    let query = format!(
        r#"SELECT COUNT(*) FROM "{}"."{}" WHERE test_name LIKE 'Concurrent stress%'"#,
        context.profile_name, context.stress_table
    );

    let count: i64 = sqlx::query_scalar(&query)
        .fetch_one(&context.pool)
        .await
        .unwrap();
    assert_eq!(count, 20);
}

// ========================================================================
// EDGE CASE COMBINATION TESTS
// ========================================================================

#[rstest]
#[tokio::test]
async fn test_update_complex_mixed_data_type_combinations(
    #[future] comprehensive_integer_test_context: ComprehensiveIntegerTestContext,
) {
    let context = comprehensive_integer_test_context.await;
    let record_id = create_initial_comprehensive_integer_record(&context, &context.mixed_integer_table).await;

    // Test complex combinations of data type updates that stress multiple validation paths
    let complex_combinations = vec![
        (
            "All boundary values",
            HashMap::from([
                ("small_int".to_string(), Value { kind: Some(Kind::NumberValue(2147483647.0)) }),
                ("big_int".to_string(), Value { kind: Some(Kind::NumberValue(9223372036854774784.0)) }),
                ("another_int".to_string(), Value { kind: Some(Kind::NumberValue(-2147483648.0)) }),
                ("another_bigint".to_string(), Value { kind: Some(Kind::NumberValue(-9223372036854774784.0)) }),
                ("nullable_int".to_string(), Value { kind: Some(Kind::NullValue(0)) }),
                ("nullable_bigint".to_string(), Value { kind: Some(Kind::NullValue(0)) }),
            ])
        ),
        (
            "Mixed nulls and values",
            HashMap::from([
                ("small_int".to_string(), Value { kind: Some(Kind::NumberValue(42.0)) }),
                ("big_int".to_string(), Value { kind: Some(Kind::NullValue(0)) }),
                ("another_int".to_string(), Value { kind: Some(Kind::NullValue(0)) }),
                ("another_bigint".to_string(), Value { kind: Some(Kind::NumberValue(1000000000000.0)) }),
                ("nullable_int".to_string(), Value { kind: Some(Kind::NumberValue(123.0)) }),
                ("nullable_bigint".to_string(), Value { kind: Some(Kind::NullValue(0)) }),
            ])
        ),
        (
            "Zero and near-zero values",
            HashMap::from([
                ("small_int".to_string(), Value { kind: Some(Kind::NumberValue(0.0)) }),
                ("big_int".to_string(), Value { kind: Some(Kind::NumberValue(1.0)) }),
                ("another_int".to_string(), Value { kind: Some(Kind::NumberValue(-1.0)) }),
                ("another_bigint".to_string(), Value { kind: Some(Kind::NumberValue(0.0)) }),
                ("nullable_int".to_string(), Value { kind: Some(Kind::NumberValue(1.0)) }),
                ("nullable_bigint".to_string(), Value { kind: Some(Kind::NumberValue(-1.0)) }),
            ])
        ),
    ];

    for (description, mut update_data) in complex_combinations {
        update_data.insert("name".to_string(), string_to_proto_value(&format!("Complex combo: {}", description)));

        let request = PutTableDataRequest {
            profile_name: context.profile_name.clone(),
            table_name: context.mixed_integer_table.clone(),
            id: record_id,
            data: update_data.clone(),
        };

        let result = put_table_data(&context.pool, request, &context.indexer_tx).await;
        assert!(result.is_ok(), "Complex combination should succeed: {}", description);

        // Verify the complex combination was stored correctly
        let query = format!(
            r#"SELECT small_int, big_int, another_int, another_bigint, nullable_int, nullable_bigint FROM "{}"."{}" WHERE id = $1"#,
            context.profile_name, context.mixed_integer_table
        );
        let row = sqlx::query(&query)
            .bind(record_id)
            .fetch_one(&context.pool)
            .await
            .unwrap();

        // Verify each field based on what was set in update_data
        for (field_name, expected_value) in update_data.iter() {
            if field_name == "name" { continue; } // Skip text field

            match expected_value.kind.as_ref().unwrap() {
                Kind::NumberValue(num) => {
                    match field_name.as_str() {
                        "small_int" | "another_int" | "nullable_int" => {
                            let stored: Option<i32> = row.get(field_name.as_str());
                            if let Some(stored_val) = stored {
                                assert_eq!(stored_val, *num as i32, "Field {} mismatch in {}", field_name, description);
                            }
                        },
                        "big_int" | "another_bigint" | "nullable_bigint" => {
                            let stored: Option<i64> = row.get(field_name.as_str());
                            if let Some(stored_val) = stored {
                                assert_eq!(stored_val, *num as i64, "Field {} mismatch in {}", field_name, description);
                            }
                        },
                        _ => {}
                    }
                },
                Kind::NullValue(_) => {
                    match field_name.as_str() {
                        "small_int" | "another_int" | "nullable_int" => {
                            let stored: Option<i32> = row.get(field_name.as_str());
                            assert!(stored.is_none(), "Field {} should be null in {}", field_name, description);
                        },
                        "big_int" | "another_bigint" | "nullable_bigint" => {
                            let stored: Option<i64> = row.get(field_name.as_str());
                            assert!(stored.is_none(), "Field {} should be null in {}", field_name, description);
                        },
                        _ => {}
                    }
                },
                _ => {}
            }
        }
    }
}
