// Additional edge case tests for decimal handling
// Add these to your test files

#[rstest]
#[tokio::test]
async fn test_decimal_negative_values_rejected(#[future] pool: PgPool) {
    let pool = pool.await;
    let negative_cases = vec![
        "decimal(-1, 0)",     // negative precision
        "decimal(5, -1)",     // negative scale
        "decimal(-5, -2)",    // both negative
    ];

    for negative_type in negative_cases {
        let request = PostTableDefinitionRequest {
            profile_name: "default".into(),
            table_name: format!("table_neg_{}", negative_type.replace(['(', ')', ',', '-'], "_")),
            columns: vec![ColumnDefinition {
                name: "amount".into(),
                field_type: negative_type.into(),
            }],
            ..Default::default()
        };

        let result = post_table_definition(&pool, request).await;
        assert!(result.is_err(), "Negative values should be rejected: {}", negative_type);
        assert_eq!(result.unwrap_err().code(), Code::InvalidArgument);
    }
}

#[rstest]
#[tokio::test]
async fn test_decimal_postgresql_limits(#[future] pool: PgPool) {
    let pool = pool.await;
    
    // Test maximum valid PostgreSQL precision (1000)
    let max_valid_request = PostTableDefinitionRequest {
        profile_name: "default".into(),
        table_name: "max_precision_test".into(),
        columns: vec![ColumnDefinition {
            name: "amount".into(),
            field_type: "decimal(1000, 0)".into(),
        }],
        ..Default::default()
    };
    
    // This should succeed (though you might want to add a limit in your code)
    let result = post_table_definition(&pool, max_valid_request).await;
    // Note: Currently your code doesn't enforce PostgreSQL's 1000 limit, 
    // so this will succeed. You may want to add that validation.
    
    // Test over PostgreSQL limit
    let over_limit_request = PostTableDefinitionRequest {
        profile_name: "default".into(),
        table_name: "over_precision_test".into(),
        columns: vec![ColumnDefinition {
            name: "amount".into(),
            field_type: "decimal(1001, 0)".into(),
        }],
        ..Default::default()
    };
    
    // This might succeed in your validation but fail at PostgreSQL level
    // Consider adding explicit validation for this
    let _result = post_table_definition(&pool, over_limit_request).await;
}

#[rstest]
#[tokio::test]
async fn test_decimal_leading_zeros_and_signs(#[future] pool: PgPool) {
    let pool = pool.await;
    let cases = vec![
        ("decimal(01, 02)", false),   // leading zeros - should be REJECTED
        ("decimal(001, 000)", false), // multiple leading zeros - should be REJECTED
        ("decimal(+5, +2)", false),   // explicit positive signs - should be REJECTED
        ("decimal(05, +2)", false),   // mixed formats - should be REJECTED
        ("decimal(2, 1)", true),      // clean format - should succeed
        ("decimal(10, 0)", true),     // clean format - should succeed
        ("decimal(5, 5)", true),      // scale equals precision - should succeed
        ("decimal(1, 0)", true),      // minimum valid case - should succeed
    ];

    for (i, (field_type, should_succeed)) in cases.into_iter().enumerate() {
        let request = PostTableDefinitionRequest {
            profile_name: "default".into(),
            // Use completely independent, valid table names
            table_name: format!("test_table_{}", i),
            columns: vec![ColumnDefinition {
                name: "amount".into(),
                field_type: field_type.into(),
            }],
            ..Default::default()
        };

        let result = post_table_definition(&pool, request).await;
        if should_succeed {
            assert!(result.is_ok(),
                   "Should succeed: '{}' but got error: {:?}",
                   field_type,
                   result.as_ref().err().map(|e| e.message()));
        } else {
            assert!(result.is_err(), "Should fail: '{}'", field_type);
            if let Err(status) = result {
                assert_eq!(status.code(), Code::InvalidArgument,
                          "Wrong error code for case '{}': {}", field_type, status.message());
            }
        }
    }
}

#[rstest]
#[tokio::test]
async fn test_decimal_extra_parameters_rejected(#[future] pool: PgPool) {
    let pool = pool.await;
    let invalid_cases = vec![
        "decimal(5,2,3)",       // too many parameters
        "decimal(5,,2)",        // double comma
        "decimal(5, 2, )",      // trailing comma
        "decimal(5,2,)",        // trailing comma variant
        "decimal(5,2,3,4)",     // way too many parameters
    ];

    for invalid_case in invalid_cases {
        let request = PostTableDefinitionRequest {
            profile_name: "default".into(),
            table_name: format!("table_{}", invalid_case.replace(['(', ')', ','], "_")),
            columns: vec![ColumnDefinition {
                name: "amount".into(),
                field_type: invalid_case.into(),
            }],
            ..Default::default()
        };

        let result = post_table_definition(&pool, request).await;
        assert!(result.is_err(), "Should reject extra parameters: {}", invalid_case);
        assert_eq!(result.unwrap_err().code(), Code::InvalidArgument);
    }
}

#[rstest]
#[tokio::test]
async fn test_decimal_floating_point_inputs_rejected(#[future] pool: PgPool) {
    let pool = pool.await;
    let floating_cases = vec![
        "decimal(5.5, 2)",      // floating point precision
        "decimal(5, 2.0)",      // floating point scale
        "decimal(5.1, 2.9)",    // both floating point
        "decimal(1.0, 0.0)",    // explicit decimals
    ];

    for floating_case in floating_cases {
        let request = PostTableDefinitionRequest {
            profile_name: "default".into(),
            table_name: format!("table_{}", floating_case.replace(['(', ')', ',', '.'], "_")),
            columns: vec![ColumnDefinition {
                name: "amount".into(),
                field_type: floating_case.into(),
            }],
            ..Default::default()
        };

        let result = post_table_definition(&pool, request).await;
        assert!(result.is_err(), "Should reject floating point: {}", floating_case);
        assert_eq!(result.unwrap_err().code(), Code::InvalidArgument);
    }
}

#[rstest]
#[tokio::test]
async fn test_decimal_whitespace_variations(#[future] pool: PgPool) {
    let pool = pool.await;
    let whitespace_cases = vec![
        ("decimal(\t5\t,\t2\t)", true),   // tabs
        ("decimal(\n5\n,\n2\n)", true),   // newlines  
        ("decimal( 5\t, 2\n)", true),     // mixed whitespace
        ("decimal(5 2)", false),          // missing comma
        ("decimal(5\t2)", false),         // tab instead of comma
    ];

    for (i, (case, should_succeed)) in whitespace_cases.into_iter().enumerate() {
        let request = PostTableDefinitionRequest {
            profile_name: "default".into(),
            table_name: format!("whitespace_test_{}", i),
            columns: vec![ColumnDefinition {
                name: "amount".into(),
                field_type: case.into(),
            }],
            ..Default::default()
        };

        let result = post_table_definition(&pool, request).await;
        if should_succeed {
            assert!(result.is_ok(), "Should handle whitespace: {}", case);
        } else {
            assert!(result.is_err(), "Should reject invalid format: {}", case);
        }
    }
}

#[rstest]
#[tokio::test]
async fn test_decimal_boundary_scale_values(#[future] pool: PgPool) {
    let pool = pool.await;
    let boundary_cases = vec![
        ("decimal(10, 10)", true),   // scale equals precision (valid)
        ("decimal(10, 11)", false),  // scale > precision (invalid, already tested)
        ("decimal(1, 0)", true),     // minimum valid case
        ("decimal(2, 1)", true),     // normal case
    ];

    for (i, (case, should_succeed)) in boundary_cases.into_iter().enumerate() {
        let request = PostTableDefinitionRequest {
            profile_name: "default".into(),
            table_name: format!("boundary_test_{}", i),
            columns: vec![ColumnDefinition {
                name: "amount".into(),
                field_type: case.into(),
            }],
            ..Default::default()
        };

        let result = post_table_definition(&pool, request).await;
        if should_succeed {
            assert!(result.is_ok(), "Should succeed: {}", case);
        } else {
            assert!(result.is_err(), "Should fail: {}", case);
        }
    }
}

#[rstest]
#[tokio::test]
async fn test_decimal_case_insensitive_variations(#[future] pool: PgPool) {
    let pool = pool.await;
    let case_variations = vec![
        "DECIMAL(5,2)",
        "Decimal(5,2)", 
        "decimal(5,2)",
        "DeCiMaL(5,2)",
    ];

    for (i, case_variant) in case_variations.into_iter().enumerate() {
        let request = PostTableDefinitionRequest {
            profile_name: "default".into(),
            table_name: format!("case_test_{}", i),
            columns: vec![ColumnDefinition {
                name: "amount".into(),
                field_type: case_variant.into(),
            }],
            ..Default::default()
        };

        let result = post_table_definition(&pool, request).await;
        assert!(result.is_ok(), "Should handle case variation: {}", case_variant);
        
        let response = result.unwrap();
        assert!(response.sql.contains("NUMERIC(5, 2)"), 
               "Should map to NUMERIC(5, 2): {}", response.sql);
    }
}

#[rstest]
#[tokio::test]
async fn test_decimal_u32_overflow_protection(#[future] pool: PgPool) {
    let pool = pool.await;
    
    // Test numbers that would overflow u32 (> 4,294,967,295)
    // Your current code uses u32::parse, so these should fail gracefully
    let overflow_cases = vec![
        "decimal(4294967296, 0)",      // u32::MAX + 1
        "decimal(0, 4294967296)",      // u32::MAX + 1 for scale
        "decimal(99999999999999, 0)",  // very large number
    ];

    for overflow_case in overflow_cases {
        let request = PostTableDefinitionRequest {
            profile_name: "default".into(),
            table_name: format!("overflow_test_{}", overflow_case.len()),
            columns: vec![ColumnDefinition {
                name: "amount".into(),
                field_type: overflow_case.into(),
            }],
            ..Default::default()
        };

        let result = post_table_definition(&pool, request).await;
        assert!(result.is_err(), "Should reject overflow values: {}", overflow_case);
        let err = result.unwrap_err();
        assert_eq!(err.code(), Code::InvalidArgument);
        // Should contain either "Invalid precision" or "Invalid scale"
        assert!(err.message().contains("Invalid") && 
               (err.message().contains("precision") || err.message().contains("scale")));
    }
}
