use crate::money_macros::dec;
use crate::{
    BHD, BaseMoney, BaseOps, CustomMoney, EUR, GBP, JPY, Money, MoneyError, RoundingStrategy, USD,
};
use std::str::FromStr;

// ==================== Money::new() Tests ====================

#[test]
fn test_new_with_usd() {
    let money = Money::<USD>::new(dec!(100.50)).unwrap();
    assert_eq!(money.amount(), dec!(100.50));
}

#[test]
fn test_new_with_zero_amount() {
    let money = Money::<EUR>::new(dec!(0)).unwrap();
    assert_eq!(money.amount(), dec!(0));
}

#[test]
fn test_new_with_negative_amount() {
    let money = Money::<GBP>::new(dec!(-50.25)).unwrap();
    assert_eq!(money.amount(), dec!(-50.25));
}

#[test]
fn test_new_with_large_amount() {
    let money = Money::<JPY>::new(dec!(999999999.99)).unwrap();
    assert_eq!(money.amount(), dec!(1000000000));
}

// ==================== PartialEq Tests ====================

#[test]
fn test_partial_eq_same_currency_same_amount() {
    let money1 = Money::<USD>::new(dec!(100.50)).unwrap();
    let money2 = Money::<USD>::new(dec!(100.50)).unwrap();
    assert_eq!(money1, money2);
}

#[test]
fn test_partial_eq_same_currency_different_amount() {
    let money1 = Money::<USD>::new(dec!(100.50)).unwrap();
    let money2 = Money::<USD>::new(dec!(100.51)).unwrap();
    assert_ne!(money1, money2);
}

// NOTE: With the new generic Money<C> API, comparing different currency types
// is prevented at compile time. The following tests are no longer applicable:
// - test_partial_eq_different_currency_same_amount
// - test_partial_eq_different_currency_different_amount
// This is actually a feature - compile-time type safety prevents currency mixing!

#[test]
fn test_partial_eq_negative_amounts() {
    let money1 = Money::<USD>::new(dec!(-100.50)).unwrap();
    let money2 = Money::<USD>::new(dec!(-100.50)).unwrap();
    assert_eq!(money1, money2);
}

// ==================== PartialOrd Tests ====================

#[test]
fn test_partial_ord_same_currency_less_than() {
    let money1 = Money::<USD>::new(dec!(100.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(200.00)).unwrap();
    assert!(money1 < money2);
}

#[test]
fn test_partial_ord_same_currency_greater_than() {
    let money1 = Money::<USD>::new(dec!(200.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(100.00)).unwrap();
    assert!(money1 > money2);
}

#[test]
fn test_partial_ord_same_currency_equal() {
    let money1 = Money::<USD>::new(dec!(100.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(100.00)).unwrap();
    assert!(money1 <= money2);
    assert!(money1 >= money2);
}

// NOTE: With the new generic Money<C> API, comparing different currency types
// won't compile (type mismatch). The following tests are no longer applicable:
// - test_partial_ord_different_currency_returns_none
// - test_partial_ord_different_currency_operators_return_false
// This is a feature - compile-time type safety prevents currency mixing!

#[test]
fn test_partial_ord_negative_amounts() {
    let money1 = Money::<USD>::new(dec!(-200.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(-100.00)).unwrap();
    assert!(money1 < money2);
}

// ==================== FromStr Tests ====================

#[test]
fn test_from_str_usd_comma_separator() {
    let money = Money::<USD>::from_str("USD 1,234.56").unwrap();
    assert_eq!(money.code(), "USD");
    assert_eq!(money.amount(), dec!(1234.56));
}

#[test]
fn test_from_str_eur_dot_separator() {
    // Dot thousands separator uses from_str_dot_thousands
    let money = Money::<EUR>::from_str_dot_thousands("EUR 1.234,56").unwrap();
    assert_eq!(money.code(), "EUR");
    assert_eq!(money.amount(), dec!(1234.56));

    // from_str only handles comma thousands separator, so dot-separator format fails
    assert!(Money::<EUR>::from_str("EUR 1.234,56").is_err());
}

#[test]
fn test_from_str_simple_amount() {
    let money = Money::<USD>::from_str("USD 100.50").unwrap();
    assert_eq!(money.code(), "USD");
    assert_eq!(money.amount(), dec!(100.50));
}

#[test]
fn test_from_str_large_amount_with_commas() {
    let money = Money::<USD>::from_str("USD 1,000,000.99").unwrap();
    assert_eq!(money.amount(), dec!(1000000.99));
}

#[test]
fn test_from_str_large_amount_with_dots() {
    // Dot thousands separator requires from_str_dot_thousands
    let money = Money::<EUR>::from_str_dot_thousands("EUR 1.000.000,99").unwrap();
    assert_eq!(money.amount(), dec!(1000000.99));
}

#[test]
fn test_from_str_zero_amount() {
    let money = Money::<USD>::from_str("USD 0.00").unwrap();
    assert_eq!(money.amount(), dec!(0.00));
}

#[test]
fn test_from_str_zero_amount_variations() {
    // Test 0.00 money compared with dec!(0)
    let money1 = Money::<USD>::from_str("USD 0.00").unwrap();
    assert_eq!(money1.amount(), dec!(0));

    // Test dec!(0) compared with 0.00
    let money2 = Money::<USD>::new(dec!(0)).unwrap();
    assert_eq!(money2.amount(), dec!(0.00));

    // Test with more zeros after decimal point
    let money3 = Money::<USD>::from_str("USD 0.000").unwrap();
    assert_eq!(money3.amount(), dec!(0.000));

    let money4 = Money::<USD>::from_str("USD 0.0000").unwrap();
    assert_eq!(money4.amount(), dec!(0.0000));

    let money5 = Money::<USD>::from_str("USD 0.00000").unwrap();
    assert_eq!(money5.amount(), dec!(0));
    assert_eq!(money5.amount(), dec!(0.00));
    assert_eq!(money5.amount(), dec!(0.00000));

    // All should be equal
    assert_eq!(money1.amount(), money2.amount());
    assert_eq!(money2.amount(), money3.amount());
    assert_eq!(money3.amount(), money4.amount());
    assert_eq!(money4.amount(), money5.amount());
}

#[test]
fn test_from_str_with_whitespace() {
    let money = Money::<USD>::from_str("  USD 100.50  ").unwrap();
    assert_eq!(money.amount(), dec!(100.50));
}

#[test]
fn test_from_str_rounding_to_minor_unit() {
    let money = Money::<USD>::from_str("USD 100.999").unwrap();
    // Should round to 2 decimal places for USD
    assert_eq!(money.amount(), dec!(101.00));
}

#[test]
fn test_from_str_invalid_no_space() {
    let result = Money::<USD>::from_str("USD100.50");
    assert!(result.is_err());
    assert!(matches!(result.unwrap_err(), MoneyError::ParseStr));
}

#[test]
fn test_from_str_invalid_currency() {
    // Note: With the new API, this needs to specify a currency type.
    // We'll use USD, but the parsing will fail because string contains "XYZ"
    let result = Money::<USD>::from_str("XYZ 100.50");
    assert!(result.is_err());
    // The error will be CurrencyMismatch since "XYZ" != "USD"
    assert!(matches!(result.unwrap_err(), MoneyError::CurrencyMismatch));
}

#[test]
fn test_from_str_invalid_amount() {
    let result = Money::<USD>::from_str("USD abc");
    assert!(result.is_err());
    assert!(matches!(result.unwrap_err(), MoneyError::ParseStr));
}

#[test]
fn test_from_str_empty_string() {
    let result = Money::<USD>::from_str("");
    assert!(result.is_err());
    assert!(matches!(result.unwrap_err(), MoneyError::ParseStr));
}

#[test]
fn test_from_str_only_currency() {
    let result = Money::<USD>::from_str("USD");
    assert!(result.is_err());
    assert!(matches!(result.unwrap_err(), MoneyError::ParseStr));
}

#[test]
fn test_from_str_only_amount() {
    let result = Money::<USD>::from_str("100.50");
    assert!(result.is_err());
    assert!(matches!(result.unwrap_err(), MoneyError::ParseStr));
}

#[test]
fn test_from_str_too_many_parts() {
    let result = Money::<USD>::from_str("USD 100.50 extra");
    assert!(result.is_err());
    assert!(matches!(result.unwrap_err(), MoneyError::ParseStr));
}

#[test]
fn test_from_str_no_decimal_separator() {
    // This actually parses successfully if it matches the thousands separator regex
    let result = Money::<USD>::from_str("USD 100.0");
    assert!(result.is_ok());
    if let Ok(money) = result {
        assert_eq!(money.amount(), dec!(100.0));
    }
}

#[test]
fn test_from_str_optional_comma_thousands_separator() {
    // Test that comma thousands separator is optional
    let with_separator = Money::<USD>::from_str("USD 1,234.56").unwrap();
    let without_separator = Money::<USD>::from_str("USD 1234.56").unwrap();
    assert_eq!(with_separator.amount(), dec!(1234.56));
    assert_eq!(without_separator.amount(), dec!(1234.56));
    assert_eq!(with_separator.amount(), without_separator.amount());
}

#[test]
fn test_from_str_optional_dot_thousands_separator() {
    // Dot thousands separator uses from_str_dot_thousands
    let with_separator = Money::<EUR>::from_str_dot_thousands("EUR 1.234,56").unwrap();
    let without_separator = Money::<EUR>::from_str_dot_thousands("EUR 1234,56").unwrap();
    assert_eq!(with_separator.amount(), dec!(1234.56));
    assert_eq!(without_separator.amount(), dec!(1234.56));
    assert_eq!(with_separator.amount(), without_separator.amount());
}

#[test]
fn test_from_str_edge_case_1000_dot_000() {
    // Test USD 1000.000 - should parse as 1000.000 and round to 1000.00
    let money = Money::<USD>::from_str("USD 1000.000").unwrap();
    assert_eq!(money.amount(), dec!(1000.00));
}

#[test]
fn test_from_str_edge_case_1000_comma_000() {
    // "USD 1000,000": comma is the decimal separator here (no proper thousands grouping),
    // so from_str (comma-thousands) rejects it; from_str_dot_thousands parses it as 1000.000
    assert!(Money::<USD>::from_str("USD 1000,000").is_err());
    let money = Money::<USD>::from_str_dot_thousands("USD 1000,000").unwrap();
    assert_eq!(money.amount(), dec!(1000.00));
}

#[test]
fn test_from_str_no_thousands_separator_various() {
    // Test various amounts without thousands separators
    // USD uses from_str (comma thousands, dot decimal)
    let usd_tests = vec![
        ("USD 100.00", dec!(100.00)),
        ("USD 1000.00", dec!(1000.00)),
        ("USD 10000.00", dec!(10000.00)),
    ];

    for (input, expected) in usd_tests {
        let money = Money::<USD>::from_str(input).unwrap();
        assert_eq!(money.amount(), expected, "Failed for input: {}", input);
    }

    // EUR amounts without thousands separator use comma as decimal separator,
    // so they require from_str_dot_thousands
    let eur_tests = vec![
        ("EUR 100,00", dec!(100.00)),
        ("EUR 1000,00", dec!(1000.00)),
        ("EUR 10000,00", dec!(10000.00)),
    ];

    for (input, expected) in eur_tests {
        let money = Money::<EUR>::from_str_dot_thousands(input).unwrap();
        assert_eq!(money.amount(), expected, "Failed for input: {}", input);
    }
}

#[test]
fn test_from_str_edge_case_variations() {
    // Cases that use comma as thousands separator (dot as decimal) → from_str
    let comma_thousands_tests = vec![
        ("USD 100.000", dec!(100.00)),    // Decimal .000 rounds to .00
        ("USD 100.0000", dec!(100.00)),   // Decimal .0000 rounds to .00
        ("USD 100,000", dec!(100000.00)), // Comma thousands separator: 100,000
        ("USD 1000.000", dec!(1000.00)),  // Decimal .000 rounds to .00
        ("USD 100.00", dec!(100.00)),
        ("USD 1000000.243", dec!(1_000_000.24)),
        ("EUR 100.000", dec!(100.00)),
        ("EUR 100.0000", dec!(100.00)),
        ("EUR 100,000", dec!(100000.00)), // Comma as thousands separator
        ("EUR 1000.000", dec!(1000.00)),
        ("EUR 100.00", dec!(100.00)),
        ("EUR 1000000.243", dec!(1_000_000.24)),
    ];

    for (input, expected) in &comma_thousands_tests {
        if input.starts_with("USD") {
            let money: Money<USD> = Money::from_str(input).unwrap();
            assert_eq!(
                money.amount(),
                *expected,
                "Failed for comma-thousands input: {}",
                input
            );
        } else if input.starts_with("EUR") {
            let money: Money<EUR> = Money::from_str(input).unwrap();
            assert_eq!(
                money.amount(),
                *expected,
                "Failed for comma-thousands input: {}",
                input
            );
        }
    }

    // Cases that use dot as thousands separator (comma as decimal) → from_str_dot_thousands
    let dot_thousands_tests = vec![
        ("USD 100,0000", dec!(100.00)),  // Comma as decimal separator
        ("USD 1000,000", dec!(1000.00)), // Comma as decimal separator
        ("USD 1.000.000,123", dec!(1_000_000.12)), // Dot thousands, comma decimal
        ("USD 100,00", dec!(100.00)),    // Comma as decimal separator
        ("USD 1000000,243", dec!(1_000_000.24)), // Comma as decimal separator
        ("EUR 100,0000", dec!(100.00)),
        ("EUR 1000,000", dec!(1000.00)),
        ("EUR 1.000.000,123", dec!(1_000_000.12)),
        ("EUR 100,00", dec!(100.00)),
        ("EUR 1000000,243", dec!(1_000_000.24)),
        ("EUR 100.000", dec!(100000.00)),
        ("EUR 1234,789", dec!(1_234.79)),
    ];

    for (input, expected) in &dot_thousands_tests {
        if input.starts_with("USD") {
            let money: Money<USD> = Money::from_str_dot_thousands(input).unwrap();
            assert_eq!(
                money.amount(),
                *expected,
                "Failed for dot-thousands input: {}",
                input
            );
        } else if input.starts_with("EUR") {
            let money: Money<EUR> = Money::from_str_dot_thousands(input).unwrap();
            assert_eq!(
                money.amount(),
                *expected,
                "Failed for dot-thousands input: {}",
                input
            );
        }
    }
}

// ==================== from_str_dot_thousands Tests ====================

#[test]
fn test_from_str_dot_thousands_basic() {
    let money = Money::<EUR>::from_str_dot_thousands("EUR 1.234,56").unwrap();
    assert_eq!(money.code(), "EUR");
    assert_eq!(money.amount(), dec!(1234.56));
}

#[test]
fn test_from_str_dot_thousands_no_thousands_separator() {
    let money = Money::<EUR>::from_str_dot_thousands("EUR 100,50").unwrap();
    assert_eq!(money.amount(), dec!(100.50));
}

#[test]
fn test_from_str_dot_thousands_integer_only() {
    let money = Money::<EUR>::from_str_dot_thousands("EUR 100").unwrap();
    assert_eq!(money.amount(), dec!(100.00));
}

#[test]
fn test_from_str_dot_thousands_large_amount() {
    let money = Money::<EUR>::from_str_dot_thousands("EUR 1.000.000,99").unwrap();
    assert_eq!(money.amount(), dec!(1000000.99));
}

#[test]
fn test_from_str_dot_thousands_no_decimal() {
    let money = Money::<EUR>::from_str_dot_thousands("EUR 1.234").unwrap();
    assert_eq!(money.amount(), dec!(1234.00));
}

#[test]
fn test_from_str_dot_thousands_zero() {
    let money = Money::<EUR>::from_str_dot_thousands("EUR 0,00").unwrap();
    assert_eq!(money.amount(), dec!(0.00));
}

#[test]
fn test_from_str_dot_thousands_rounding() {
    // EUR has 2 decimal places; comma is the decimal separator, so 100,999 means 100.999
    // which rounds to 101.00
    let money = Money::<EUR>::from_str_dot_thousands("EUR 100,999").unwrap();
    assert_eq!(money.amount(), dec!(101.00));
}

#[test]
fn test_from_str_dot_thousands_with_whitespace() {
    let money = Money::<EUR>::from_str_dot_thousands("  EUR 1.234,56  ").unwrap();
    assert_eq!(money.amount(), dec!(1234.56));
}

#[test]
fn test_from_str_dot_thousands_currency_mismatch() {
    let result = Money::<USD>::from_str_dot_thousands("EUR 1.234,56");
    assert!(result.is_err());
    assert!(matches!(result.unwrap_err(), MoneyError::CurrencyMismatch));
}

#[test]
fn test_from_str_dot_thousands_invalid_format() {
    // Comma-thousands / dot-decimal format is rejected
    assert!(Money::<USD>::from_str_dot_thousands("USD 1,234.56").is_err());
}

#[test]
fn test_from_str_dot_thousands_invalid_empty() {
    assert!(Money::<EUR>::from_str_dot_thousands("").is_err());
}

#[test]
fn test_from_str_dot_thousands_invalid_no_space() {
    assert!(Money::<EUR>::from_str_dot_thousands("EUR1.234,56").is_err());
}

#[test]
fn test_from_str_dot_thousands_invalid_currency_mismatch() {
    let result = Money::<EUR>::from_str_dot_thousands("USD 100,00");
    assert!(result.is_err());
    assert!(matches!(result.unwrap_err(), MoneyError::CurrencyMismatch));
}

#[test]
fn test_from_str_dot_thousands_optional_separator() {
    // Thousands separator is optional
    let with_sep = Money::<EUR>::from_str_dot_thousands("EUR 1.234,56").unwrap();
    let without_sep = Money::<EUR>::from_str_dot_thousands("EUR 1234,56").unwrap();
    assert_eq!(with_sep.amount(), without_sep.amount());
    assert_eq!(with_sep.amount(), dec!(1234.56));
}

// ==================== Display Tests ====================

#[test]
fn test_display_format() {
    let money = Money::<USD>::new(dec!(1234.56)).unwrap();
    let display_str = format!("{}", money);
    assert_eq!(display_str, "USD 1,234.56");
}

#[test]
fn test_display_negative() {
    let money = Money::<USD>::new(dec!(-1234.56)).unwrap();
    let display_str = format!("{}", money);
    assert_eq!(display_str, "USD -1,234.56");
}

#[test]
fn test_display_zero() {
    let money = Money::<USD>::new(dec!(0.00)).unwrap();
    let display_str = format!("{}", money);
    assert_eq!(display_str, "USD 0.00");
}

// ==================== BaseMoney Trait Tests ====================

#[test]
fn test_base_money_amount() {
    let money = Money::<USD>::new(dec!(123.45)).unwrap();
    assert_eq!(money.amount(), dec!(123.45));
}

#[test]
fn test_base_money_round() {
    let money = Money::<USD>::new(dec!(123.456)).unwrap();
    let rounded = money.round();
    assert_eq!(rounded.amount(), dec!(123.46));
}

#[test]
fn test_base_money_round_jpy_no_minor_unit() {
    let money = Money::<JPY>::new(dec!(123.56)).unwrap();
    let rounded = money.round();
    assert_eq!(rounded.amount(), dec!(124));
}

#[test]
fn test_base_money_name() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    assert_eq!(money.name(), "United States dollar");
}

#[test]
fn test_base_money_symbol() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    assert_eq!(money.symbol(), "$");
}

#[test]
fn test_base_money_code() {
    let money = Money::<EUR>::new(dec!(100.00)).unwrap();
    assert_eq!(money.code(), "EUR");
}

#[test]
fn test_base_money_numeric_code() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    assert_eq!(money.numeric_code(), 840);
}

#[test]
fn test_base_money_minor_unit() {
    let usd_money = Money::<USD>::new(dec!(100.00)).unwrap();
    assert_eq!(usd_money.minor_unit(), 2);

    let jpy_money = Money::<JPY>::new(dec!(100)).unwrap();
    assert_eq!(jpy_money.minor_unit(), 0);
}

#[test]
fn test_base_money_minor_amount() {
    let money = Money::<USD>::new(dec!(123.45)).unwrap();
    assert_eq!(money.minor_amount().unwrap(), 12345);
}

#[test]
fn test_base_money_minor_amount_negative() {
    let money = Money::<USD>::new(dec!(-123.45)).unwrap();
    assert_eq!(money.minor_amount().unwrap(), -12345);
}

#[test]
fn test_base_money_minor_amount_jpy() {
    let money = Money::<JPY>::new(dec!(123)).unwrap();
    assert_eq!(money.minor_amount().unwrap(), 123);
}

#[test]
fn test_base_money_thousand_separator() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    assert_eq!(money.thousand_separator(), ",");
}

#[test]
fn test_base_money_decimal_separator() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    assert_eq!(money.decimal_separator(), ".");
}

#[test]
fn test_base_money_is_zero_true() {
    let money = Money::<USD>::new(dec!(0)).unwrap();
    assert!(money.is_zero());
}

#[test]
fn test_base_money_is_zero_false() {
    let money = Money::<USD>::new(dec!(0.01)).unwrap();
    assert!(!money.is_zero());
}

#[test]
fn test_base_money_is_positive() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    assert!(money.is_positive());
}

#[test]
fn test_base_money_is_negative() {
    let money = Money::<USD>::new(dec!(-100.00)).unwrap();
    assert!(money.is_negative());
}

#[test]
fn test_base_money_format_code() {
    let money = Money::<USD>::new(dec!(1234.56)).unwrap();
    assert_eq!(money.format_code(), "USD 1,234.56");
}

#[test]
fn test_base_money_format_code_negative() {
    let money = Money::<USD>::new(dec!(-1234.56)).unwrap();
    assert_eq!(money.format_code(), "USD -1,234.56");
}

#[test]
fn test_base_money_format_symbol() {
    let money = Money::<USD>::new(dec!(1234.56)).unwrap();
    assert_eq!(money.format_symbol(), "$1,234.56");
}

#[test]
fn test_base_money_format_symbol_negative() {
    let money = Money::<USD>::new(dec!(-1234.56)).unwrap();
    assert_eq!(money.format_symbol(), "-$1,234.56");
}

#[test]
fn test_base_money_format_code_minor() {
    let money = Money::<USD>::new(dec!(1234.56)).unwrap();
    let formatted = money.format_code_minor();
    assert!(formatted.contains("USD"));
    assert!(formatted.contains("123,456"));
}

#[test]
fn test_base_money_format_code_minor_negative() {
    let money = Money::<USD>::new(dec!(-1234.56)).unwrap();
    let formatted = money.format_code_minor();
    assert!(formatted.contains("USD"));
    assert!(formatted.contains("-123,456"));
    // Assert full display string
    assert_eq!(formatted, "USD -123,456 ¢");
}

#[test]
fn test_base_money_format_symbol_minor() {
    let money = Money::<USD>::new(dec!(1234.56)).unwrap();
    let formatted = money.format_symbol_minor();
    assert!(formatted.contains("$"));
    assert!(formatted.contains("123,456"));
    // Assert full display string
    assert_eq!(formatted, "$123,456 ¢");
}

#[test]
fn test_base_money_format_symbol_minor_negative() {
    let money = Money::<USD>::new(dec!(-1234.56)).unwrap();
    let formatted = money.format_symbol_minor();
    assert!(formatted.contains("$"));
    assert!(formatted.contains("123,456"));
    // Assert full display string
    assert_eq!(formatted, "-$123,456 ¢");
}

#[test]
fn test_base_money_display() {
    let money = Money::<EUR>::new(dec!(1234.56)).unwrap();
    assert_eq!(money.display(), "EUR 1.234,56");
}

// ==================== BaseOps Trait Tests ====================

#[test]
fn test_base_ops_abs_positive() {
    let money = Money::<USD>::new(dec!(100.50)).unwrap();
    let abs_money = money.abs();
    assert_eq!(abs_money.amount(), dec!(100.50));
}

#[test]
fn test_base_ops_abs_negative() {
    let money = Money::<USD>::new(dec!(-100.50)).unwrap();
    let abs_money = money.abs();
    assert_eq!(abs_money.amount(), dec!(100.50));
}

#[test]
fn test_base_ops_abs_zero() {
    let money = Money::<USD>::new(dec!(0)).unwrap();
    let abs_money = money.abs();
    assert_eq!(abs_money.amount(), dec!(0));
}

#[test]
fn test_base_ops_min() {
    let money1 = Money::<USD>::new(dec!(100.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(200.00)).unwrap();
    let min_money = money1.min(money2);
    assert_eq!(min_money.amount(), dec!(100.00));
}

#[test]
fn test_base_ops_min_negative() {
    let money1 = Money::<USD>::new(dec!(-100.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(200.00)).unwrap();
    let min_money = money1.min(money2);
    assert_eq!(min_money.amount(), dec!(-100.00));
}

#[test]
fn test_base_ops_max() {
    let money1 = Money::<USD>::new(dec!(100.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(200.00)).unwrap();
    let max_money = money1.max(money2);
    assert_eq!(max_money.amount(), dec!(200.00));
}

#[test]
fn test_base_ops_max_negative() {
    let money1 = Money::<USD>::new(dec!(-100.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(200.00)).unwrap();
    let max_money = money1.max(money2);
    assert_eq!(max_money.amount(), dec!(200.00));
}

#[test]
fn test_base_ops_clamp_within_range() {
    let money = Money::<USD>::new(dec!(150.00)).unwrap();
    let min = Money::<USD>::new(dec!(100.00)).unwrap();
    let max = Money::<USD>::new(dec!(200.00)).unwrap();
    let clamped = money.clamp(min, max);
    assert_eq!(clamped.amount(), dec!(150.00));
}

#[test]
fn test_base_ops_clamp_below_range() {
    let money = Money::<USD>::new(dec!(50.00)).unwrap();
    let min = Money::<USD>::new(dec!(100.00)).unwrap();
    let max = Money::<USD>::new(dec!(200.00)).unwrap();
    let clamped = money.clamp(min, max);
    assert_eq!(clamped.amount(), dec!(100.00));
}

#[test]
fn test_base_ops_clamp_above_range() {
    let money = Money::<USD>::new(dec!(250.00)).unwrap();
    let min = Money::<USD>::new(dec!(100.00)).unwrap();
    let max = Money::<USD>::new(dec!(200.00)).unwrap();
    let clamped = money.clamp(min, max);
    assert_eq!(clamped.amount(), dec!(200.00));
}

/// Test BaseOps abs, min, max, clamp

#[test]
fn test_money_abs() {
    let money = Money::<USD>::from_decimal(dec!(-1234));
    let abs_money = money.abs();
    assert_eq!(abs_money.amount(), dec!(1234));
}

#[test]
fn test_money_min() {
    let money = Money::<USD>::from_decimal(dec!(-1234));
    let money2 = Money::<USD>::from_decimal(dec!(1234));
    let min_money = money.min(money2);
    assert_eq!(min_money, money);
}

#[test]
fn test_money_max() {
    let money = Money::<USD>::from_decimal(dec!(-1234));
    let money2 = Money::<USD>::from_decimal(dec!(1234));
    let max_money = money.max(money2);
    assert_eq!(max_money, money2);
}

#[test]
fn test_money_clamp() {
    let money = Money::<USD>::from_decimal(dec!(1234));
    let min_budget = Money::<USD>::from_decimal(dec!(500));
    let max_budget = Money::<USD>::from_decimal(dec!(2000));
    let clamped = money.clamp(min_budget, max_budget);
    assert_eq!(clamped, money);

    let money = Money::<USD>::from_decimal(dec!(430));
    let min_budget = Money::<USD>::from_decimal(dec!(500));
    let max_budget = Money::<USD>::from_decimal(dec!(2000));
    let clamped = money.clamp(min_budget, max_budget);
    assert_eq!(clamped, min_budget);

    let money = Money::<USD>::from_decimal(dec!(3000));
    let min_budget = Money::<USD>::from_decimal(dec!(500));
    let max_budget = Money::<USD>::from_decimal(dec!(2000));
    let clamped = money.clamp(min_budget, max_budget);
    assert_eq!(clamped, max_budget);
}

#[test]
fn test_base_ops_add_decimal() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.add(dec!(50.00)).unwrap();
    assert_eq!(result.amount(), dec!(150.00));
}

#[test]
fn test_base_ops_add_decimal_negative() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.add(dec!(-50.00)).unwrap();
    assert_eq!(result.amount(), dec!(50.00));
}

#[test]
fn test_base_ops_add_decimal_rounds() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.add(dec!(0.005)).unwrap();
    // Banker's rounding: 0.005 rounds to 0.00 (rounds to nearest even)
    assert_eq!(result.amount(), dec!(100.00));
}

#[test]
fn test_base_ops_sub_decimal() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.sub(dec!(50.00)).unwrap();
    assert_eq!(result.amount(), dec!(50.00));
}

#[test]
fn test_base_ops_sub_decimal_negative() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.sub(dec!(-50.00)).unwrap();
    assert_eq!(result.amount(), dec!(150.00));
}

#[test]
fn test_base_ops_sub_decimal_rounds() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.sub(dec!(0.005)).unwrap();
    assert_eq!(result.amount(), dec!(100.00));
}

#[test]
fn test_base_ops_mul_decimal() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.mul(dec!(2.5)).unwrap();
    assert_eq!(result.amount(), dec!(250.00));
}

#[test]
fn test_base_ops_mul_decimal_negative() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.mul(dec!(-2.0)).unwrap();
    assert_eq!(result.amount(), dec!(-200.00));
}

#[test]
fn test_base_ops_mul_decimal_rounds() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.mul(dec!(1.005)).unwrap();
    assert_eq!(result.amount(), dec!(100.50));
}

#[test]
fn test_base_ops_div_decimal() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.div(dec!(2.0)).unwrap();
    assert_eq!(result.amount(), dec!(50.00));
}

#[test]
fn test_base_ops_div_decimal_negative() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.div(dec!(-2.0)).unwrap();
    assert_eq!(result.amount(), dec!(-50.00));
}

#[test]
fn test_base_ops_div_decimal_rounds() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.div(dec!(3.0)).unwrap();
    assert_eq!(result.amount(), dec!(33.33));
}

#[test]
fn test_base_ops_div_decimal_zero_error() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.div(dec!(0));
    assert!(result.is_err());
    assert!(matches!(
        result.unwrap_err(),
        MoneyError::ArithmeticOverflow
    ));
}

// ==================== BaseOps with Money Type Tests ====================

#[test]
fn test_base_ops_add_money() {
    let money1 = Money::<USD>::new(dec!(100.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(50.00)).unwrap();
    let result = money1.add(money2).unwrap();
    assert_eq!(result.amount(), dec!(150.00));
}

#[test]
fn test_base_ops_add_money_negative() {
    let money1 = Money::<USD>::new(dec!(100.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(-50.00)).unwrap();
    let result = money1.add(money2).unwrap();
    assert_eq!(result.amount(), dec!(50.00));
}

#[test]
fn test_base_ops_add_money_rounds() {
    let money1 = Money::<USD>::new(dec!(100.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(0.005)).unwrap();
    let result = money1.add(money2).unwrap();
    // Banker's rounding: 0.005 rounds to 0.00 (rounds to nearest even)
    assert_eq!(result.amount(), dec!(100.00));
}

#[test]
fn test_base_ops_sub_money() {
    let money1 = Money::<USD>::new(dec!(100.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(50.00)).unwrap();
    let result = money1.sub(money2).unwrap();
    assert_eq!(result.amount(), dec!(50.00));
}

#[test]
fn test_base_ops_sub_money_negative() {
    let money1 = Money::<USD>::new(dec!(100.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(-50.00)).unwrap();
    let result = money1.sub(money2).unwrap();
    assert_eq!(result.amount(), dec!(150.00));
}

#[test]
fn test_base_ops_sub_money_rounds() {
    let money1 = Money::<USD>::new(dec!(100.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(0.005)).unwrap();
    let result = money1.sub(money2).unwrap();
    assert_eq!(result.amount(), dec!(100.00));
}

#[test]
fn test_base_ops_mul_money() {
    let money1 = Money::<USD>::new(dec!(100.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(2.5)).unwrap();
    let result = money1.mul(money2).unwrap();
    assert_eq!(result.amount(), dec!(250.00));
}

#[test]
fn test_base_ops_mul_money_negative() {
    let money1 = Money::<USD>::new(dec!(100.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(-2.0)).unwrap();
    let result = money1.mul(money2).unwrap();
    assert_eq!(result.amount(), dec!(-200.00));
}

#[test]
fn test_base_ops_mul_money_rounds() {
    let money1 = Money::<USD>::new(dec!(100.00)).unwrap();
    // Money2 will be rounded to 1.00 when created because USD has 2 decimal places
    let money2 = Money::<USD>::new(dec!(1.005)).unwrap();
    let result = money1.mul(money2).unwrap();
    // 100.00 * 1.00 = 100.00
    assert_eq!(result.amount(), dec!(100.00));
}

#[test]
fn test_base_ops_div_money() {
    let money1 = Money::<USD>::new(dec!(100.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(2.0)).unwrap();
    let result = money1.div(money2).unwrap();
    assert_eq!(result.amount(), dec!(50.00));
}

#[test]
fn test_base_ops_div_money_negative() {
    let money1 = Money::<USD>::new(dec!(100.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(-2.0)).unwrap();
    let result = money1.div(money2).unwrap();
    assert_eq!(result.amount(), dec!(-50.00));
}

#[test]
fn test_base_ops_div_money_rounds() {
    let money1 = Money::<USD>::new(dec!(100.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(3.0)).unwrap();
    let result = money1.div(money2).unwrap();
    assert_eq!(result.amount(), dec!(33.33));
}

#[test]
fn test_base_ops_div_money_zero_error() {
    let money1 = Money::<USD>::new(dec!(100.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(0)).unwrap();
    let result = money1.div(money2);
    assert!(result.is_err());
    assert!(matches!(
        result.unwrap_err(),
        MoneyError::ArithmeticOverflow
    ));
}

// ==================== BaseOps with f64 Type Tests ====================

#[test]
fn test_base_ops_add_f64() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.add(50.0_f64).unwrap();
    assert_eq!(result.amount(), dec!(150.00));
}

#[test]
fn test_base_ops_add_f64_negative() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.add(-50.0_f64).unwrap();
    assert_eq!(result.amount(), dec!(50.00));
}

#[test]
fn test_base_ops_add_f64_rounds() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.add(0.005_f64).unwrap();
    // Banker's rounding: 0.005 rounds to 0.00 (rounds to nearest even)
    assert_eq!(result.amount(), dec!(100.00));
}

#[test]
fn test_base_ops_sub_f64() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.sub(50.0_f64).unwrap();
    assert_eq!(result.amount(), dec!(50.00));
}

#[test]
fn test_base_ops_sub_f64_negative() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.sub(-50.0_f64).unwrap();
    assert_eq!(result.amount(), dec!(150.00));
}

#[test]
fn test_base_ops_sub_f64_rounds() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.sub(0.005_f64).unwrap();
    assert_eq!(result.amount(), dec!(100.00));
}

#[test]
fn test_base_ops_mul_f64() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.mul(2.5_f64).unwrap();
    assert_eq!(result.amount(), dec!(250.00));
}

#[test]
fn test_base_ops_mul_f64_negative() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.mul(-2.0_f64).unwrap();
    assert_eq!(result.amount(), dec!(-200.00));
}

#[test]
fn test_base_ops_mul_f64_rounds() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.mul(1.005_f64).unwrap();
    assert_eq!(result.amount(), dec!(100.50));
}

#[test]
fn test_base_ops_div_f64() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.div(2.0_f64).unwrap();
    assert_eq!(result.amount(), dec!(50.00));
}

#[test]
fn test_base_ops_div_f64_negative() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.div(-2.0_f64).unwrap();
    assert_eq!(result.amount(), dec!(-50.00));
}

#[test]
fn test_base_ops_div_f64_rounds() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.div(3.0_f64).unwrap();
    assert_eq!(result.amount(), dec!(33.33));
}

#[test]
fn test_base_ops_div_f64_zero_error() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.div(0.0_f64);
    assert!(result.is_err());
    assert!(matches!(
        result.unwrap_err(),
        MoneyError::ArithmeticOverflow
    ));
}

// ==================== BaseOps with i32 Type Tests ====================

#[test]
fn test_base_ops_add_i32() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.add(50_i32).unwrap();
    assert_eq!(result.amount(), dec!(150.00));
}

#[test]
fn test_base_ops_add_i32_negative() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.add(-50_i32).unwrap();
    assert_eq!(result.amount(), dec!(50.00));
}

#[test]
fn test_base_ops_sub_i32() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.sub(50_i32).unwrap();
    assert_eq!(result.amount(), dec!(50.00));
}

#[test]
fn test_base_ops_sub_i32_negative() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.sub(-50_i32).unwrap();
    assert_eq!(result.amount(), dec!(150.00));
}

#[test]
fn test_base_ops_mul_i32() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.mul(3_i32).unwrap();
    assert_eq!(result.amount(), dec!(300.00));
}

#[test]
fn test_base_ops_mul_i32_negative() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.mul(-2_i32).unwrap();
    assert_eq!(result.amount(), dec!(-200.00));
}

#[test]
fn test_base_ops_div_i32() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.div(2_i32).unwrap();
    assert_eq!(result.amount(), dec!(50.00));
}

#[test]
fn test_base_ops_div_i32_negative() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.div(-2_i32).unwrap();
    assert_eq!(result.amount(), dec!(-50.00));
}

#[test]
fn test_base_ops_div_i32_rounds() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.div(3_i32).unwrap();
    assert_eq!(result.amount(), dec!(33.33));
}

#[test]
fn test_base_ops_div_i32_zero_error() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.div(0_i32);
    assert!(result.is_err());
    assert!(matches!(
        result.unwrap_err(),
        MoneyError::ArithmeticOverflow
    ));
}

// ==================== BaseOps with i64 Type Tests ====================

#[test]
fn test_base_ops_add_i64() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.add(50_i64).unwrap();
    assert_eq!(result.amount(), dec!(150.00));
}

#[test]
fn test_base_ops_add_i64_negative() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.add(-50_i64).unwrap();
    assert_eq!(result.amount(), dec!(50.00));
}

#[test]
fn test_base_ops_sub_i64() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.sub(50_i64).unwrap();
    assert_eq!(result.amount(), dec!(50.00));
}

#[test]
fn test_base_ops_sub_i64_negative() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.sub(-50_i64).unwrap();
    assert_eq!(result.amount(), dec!(150.00));
}

#[test]
fn test_base_ops_mul_i64() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.mul(3_i64).unwrap();
    assert_eq!(result.amount(), dec!(300.00));
}

#[test]
fn test_base_ops_mul_i64_negative() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.mul(-2_i64).unwrap();
    assert_eq!(result.amount(), dec!(-200.00));
}

#[test]
fn test_base_ops_div_i64() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.div(2_i64).unwrap();
    assert_eq!(result.amount(), dec!(50.00));
}

#[test]
fn test_base_ops_div_i64_negative() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.div(-2_i64).unwrap();
    assert_eq!(result.amount(), dec!(-50.00));
}

#[test]
fn test_base_ops_div_i64_rounds() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.div(3_i64).unwrap();
    assert_eq!(result.amount(), dec!(33.33));
}

#[test]
fn test_base_ops_div_i64_zero_error() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.div(0_i64);
    assert!(result.is_err());
    assert!(matches!(
        result.unwrap_err(),
        MoneyError::ArithmeticOverflow
    ));
}

// ==================== BaseOps with i128 Type Tests ====================

#[test]
fn test_base_ops_add_i128() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.add(50_i128).unwrap();
    assert_eq!(result.amount(), dec!(150.00));
}

#[test]
fn test_base_ops_add_i128_negative() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.add(-50_i128).unwrap();
    assert_eq!(result.amount(), dec!(50.00));
}

#[test]
fn test_base_ops_sub_i128() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.sub(50_i128).unwrap();
    assert_eq!(result.amount(), dec!(50.00));
}

#[test]
fn test_base_ops_sub_i128_negative() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.sub(-50_i128).unwrap();
    assert_eq!(result.amount(), dec!(150.00));
}

#[test]
fn test_base_ops_mul_i128() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.mul(3_i128).unwrap();
    assert_eq!(result.amount(), dec!(300.00));
}

#[test]
fn test_base_ops_mul_i128_negative() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.mul(-2_i128).unwrap();
    assert_eq!(result.amount(), dec!(-200.00));
}

#[test]
fn test_base_ops_div_i128() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.div(2_i128).unwrap();
    assert_eq!(result.amount(), dec!(50.00));
}

#[test]
fn test_base_ops_div_i128_negative() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.div(-2_i128).unwrap();
    assert_eq!(result.amount(), dec!(-50.00));
}

#[test]
fn test_base_ops_div_i128_rounds() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.div(3_i128).unwrap();
    assert_eq!(result.amount(), dec!(33.33));
}

#[test]
fn test_base_ops_div_i128_zero_error() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.div(0_i128);
    assert!(result.is_err());
    assert!(matches!(
        result.unwrap_err(),
        MoneyError::ArithmeticOverflow
    ));
}

// ==================== CustomMoney Trait Tests ====================

#[test]
fn test_custom_money_round_with_bankers_rounding() {
    let money = Money::<USD>::new(dec!(123.456)).unwrap();
    let rounded = money.round_with(2, RoundingStrategy::BankersRounding);
    assert_eq!(rounded.amount(), dec!(123.46));
}

#[test]
fn test_custom_money_round_with_half_up() {
    let money = Money::<USD>::new(dec!(123.445)).unwrap();
    let rounded = money.round_with(2, RoundingStrategy::HalfUp);
    assert_eq!(rounded.amount(), dec!(123.44));
}

#[test]
fn test_custom_money_round_with_half_down() {
    let money = Money::<USD>::new(dec!(123.445)).unwrap();
    let rounded = money.round_with(2, RoundingStrategy::HalfDown);
    assert_eq!(rounded.amount(), dec!(123.44));
}

#[test]
fn test_custom_money_round_with_ceil() {
    let money = Money::<USD>::new(dec!(123.441)).unwrap();
    let rounded = money.round_with(2, RoundingStrategy::Ceil);
    assert_eq!(rounded.amount(), dec!(123.44));
}

#[test]
fn test_custom_money_round_with_floor() {
    let money = Money::<USD>::new(dec!(123.449)).unwrap();
    let rounded = money.round_with(2, RoundingStrategy::Floor);
    assert_eq!(rounded.amount(), dec!(123.45));
}

// ==================== Operator Tests (Money + Money) ====================

#[test]
fn test_add_money_to_money() {
    let money1 = Money::<USD>::new(dec!(100.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(50.00)).unwrap();
    let result = money1 + money2;
    assert_eq!(result.amount(), dec!(150.00));
}

#[test]
fn test_add_money_negative() {
    let money1 = Money::<USD>::new(dec!(100.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(-50.00)).unwrap();
    let result = money1 + money2;
    assert_eq!(result.amount(), dec!(50.00));
}

#[test]
fn test_sub_money_from_money() {
    let money1 = Money::<USD>::new(dec!(100.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(50.00)).unwrap();
    let result = money1 - money2;
    assert_eq!(result.amount(), dec!(50.00));
}

#[test]
fn test_sub_money_negative_result() {
    let money1 = Money::<USD>::new(dec!(50.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money1 - money2;
    assert_eq!(result.amount(), dec!(-50.00));
}

#[test]
fn test_mul_money_by_money() {
    let money1 = Money::<USD>::new(dec!(10.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(5.00)).unwrap();
    let result = money1 * money2;
    assert_eq!(result.amount(), dec!(50.00));
}

#[test]
fn test_mul_money_negative() {
    let money1 = Money::<USD>::new(dec!(10.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(-5.00)).unwrap();
    let result = money1 * money2;
    assert_eq!(result.amount(), dec!(-50.00));
}

#[test]
fn test_div_money_by_money() {
    let money1 = Money::<USD>::new(dec!(100.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(5.00)).unwrap();
    let result = money1 / money2;
    assert_eq!(result.amount(), dec!(20.00));
}

#[test]
fn test_div_money_negative() {
    let money1 = Money::<USD>::new(dec!(100.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(-5.00)).unwrap();
    let result = money1 / money2;
    assert_eq!(result.amount(), dec!(-20.00));
}

#[test]
#[should_panic(expected = "division operation")]
fn test_div_money_by_zero_panic() {
    let money1 = Money::<USD>::new(dec!(100.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(0)).unwrap();
    let _ = money1 / money2;
}

// ==================== Operator Tests (Money + Decimal) ====================

#[test]
fn test_add_decimal_to_money() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money + dec!(50.00);
    assert_eq!(result.amount(), dec!(150.00));
}

#[test]
fn test_sub_decimal_from_money() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money - dec!(50.00);
    assert_eq!(result.amount(), dec!(50.00));
}

#[test]
fn test_mul_money_by_decimal() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money * dec!(2.5);
    assert_eq!(result.amount(), dec!(250.00));
}

#[test]
fn test_div_money_by_decimal() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money / dec!(2.0);
    assert_eq!(result.amount(), dec!(50.00));
}

#[test]
#[should_panic(expected = "division operation")]
fn test_div_money_by_decimal_zero_panic() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let _ = money / dec!(0);
}

// ==================== Operator Tests (Decimal + Money) ====================

#[test]
fn test_add_money_to_decimal() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = dec!(50.00) + money;
    assert_eq!(result.amount(), dec!(150.00));
}

#[test]
fn test_sub_money_from_decimal() {
    let money = Money::<USD>::new(dec!(50.00)).unwrap();
    let result = dec!(100.00) - money;
    assert_eq!(result.amount(), dec!(50.00));
}

#[test]
fn test_mul_decimal_by_money() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = dec!(2.5) * money;
    assert_eq!(result.amount(), dec!(250.00));
}

#[test]
fn test_div_decimal_by_money() {
    let money = Money::<USD>::new(dec!(5.00)).unwrap();
    let result = dec!(100.00) / money;
    assert_eq!(result.amount(), dec!(20.00));
}

#[test]
#[should_panic(expected = "division operation")]
fn test_div_decimal_by_money_zero_panic() {
    let money = Money::<USD>::new(dec!(0)).unwrap();
    let _ = dec!(100.00) / money;
}

// ==================== Assignment Operator Tests ====================

#[test]
fn test_add_assign_money() {
    let mut money1 = Money::<USD>::new(dec!(100.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(50.00)).unwrap();
    money1 += money2;
    assert_eq!(money1.amount(), dec!(150.00));
}

#[test]
fn test_sub_assign_money() {
    let mut money1 = Money::<USD>::new(dec!(100.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(50.00)).unwrap();
    money1 -= money2;
    assert_eq!(money1.amount(), dec!(50.00));
}

#[test]
fn test_mul_assign_money() {
    let mut money1 = Money::<USD>::new(dec!(10.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(5.00)).unwrap();
    money1 *= money2;
    assert_eq!(money1.amount(), dec!(50.00));
}

#[test]
fn test_div_assign_money() {
    let mut money1 = Money::<USD>::new(dec!(100.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(5.00)).unwrap();
    money1 /= money2;
    assert_eq!(money1.amount(), dec!(20.00));
}

#[test]
#[should_panic(expected = "division operation")]
fn test_div_assign_zero_panic() {
    let mut money1 = Money::<USD>::new(dec!(100.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(0)).unwrap();
    money1 /= money2;
}

// ==================== Negation Operator Tests ====================

#[test]
fn test_neg_positive_money() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let negated = -money;
    assert_eq!(negated.amount(), dec!(-100.00));
}

#[test]
fn test_neg_negative_money() {
    let money = Money::<USD>::new(dec!(-100.00)).unwrap();
    let negated = -money;
    assert_eq!(negated.amount(), dec!(100.00));
}

#[test]
fn test_neg_zero_money() {
    let money = Money::<USD>::new(dec!(0)).unwrap();
    let negated = -money;
    assert_eq!(negated.amount(), dec!(0));
}

// ==================== Clone and Copy Tests ====================

#[test]
fn test_clone() {
    let money1 = Money::<USD>::new(dec!(100.00)).unwrap();
    let money2 = money1.clone();
    assert_eq!(money1, money2);
    assert_eq!(money1.amount(), money2.amount());
    assert_eq!(money1.code(), money2.code());
}

#[test]
fn test_copy() {
    let money1 = Money::<USD>::new(dec!(100.00)).unwrap();
    let money2 = money1; // Copy happens here
    // Both should still be usable
    assert_eq!(money1.amount(), dec!(100.00));
    assert_eq!(money2.amount(), dec!(100.00));
}

// ==================== Debug Tests ====================

#[test]
fn test_debug() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let debug_str = format!("{:?}", money);
    assert!(debug_str.contains("Money"));
}

// ==================== Edge Cases and Complex Scenarios ====================

#[test]
fn test_very_large_amount() {
    let money = Money::<USD>::new(dec!(999999999999999.99)).unwrap();
    assert_eq!(money.amount(), dec!(999999999999999.99));
}

#[test]
fn test_very_small_decimal() {
    let money = Money::<USD>::new(dec!(0.001)).unwrap();
    let rounded = money.round();
    assert_eq!(rounded.amount(), dec!(0.00));
}

#[test]
fn test_chain_operations() {
    let money1 = Money::<USD>::new(dec!(100.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(50.00)).unwrap();
    let money3 = Money::<USD>::new(dec!(25.00)).unwrap();
    let result = money1 + money2 - money3;
    assert_eq!(result.amount(), dec!(125.00));
}

#[test]
fn test_complex_calculation() {
    let base = Money::<USD>::new(dec!(100.00)).unwrap();
    let tax_rate = dec!(1.15);
    let discount = dec!(10.00);
    let result = (base * tax_rate) - discount;
    assert_eq!(result.amount(), dec!(105.00));
}

#[test]
fn test_jpy_no_decimal_places() {
    let money = Money::<JPY>::new(dec!(100.50)).unwrap();
    let rounded = money.round();
    // Banker's rounding: 100.50 rounds to 100 (rounds to nearest even)
    assert_eq!(rounded.amount(), dec!(100));
}

#[test]
fn test_bhd_three_decimal_places() {
    let money = Money::<BHD>::new(dec!(100.1234)).unwrap();
    let rounded = money.round();
    assert_eq!(rounded.amount(), dec!(100.123));
}

#[test]
fn test_parse_and_format_roundtrip() {
    let original_str = "USD 1,234.56";
    let money: Money<USD> = Money::from_str(original_str).unwrap();
    let formatted = money.format_code();
    assert_eq!(formatted, original_str);
}

#[test]
fn test_equality_after_rounding() {
    let money1 = Money::<USD>::new(dec!(100.004)).unwrap();
    let money2 = Money::<USD>::new(dec!(100.005)).unwrap();
    let rounded1 = money1.round();
    let rounded2 = money2.round();
    assert_eq!(rounded1, rounded2); // Both should round to 100.00
}

#[test]
fn test_minor_amount_with_three_decimal_currency() {
    let money = Money::<BHD>::new(dec!(100.123)).unwrap();
    assert_eq!(money.minor_amount().unwrap(), 100123);
}

#[test]
fn test_multiple_operations_maintain_precision() {
    let money = Money::<USD>::new(dec!(100.00)).unwrap();
    let result = money.mul(dec!(1.1)).unwrap();
    let result = result.div(dec!(1.1)).unwrap();
    assert_eq!(result.amount(), dec!(100.00));
}

#[test]
fn test_zero_amount_operations() {
    let zero = Money::<USD>::new(dec!(0)).unwrap();
    let hundred = Money::<USD>::new(dec!(100.00)).unwrap();

    let result = zero + hundred;
    assert_eq!(result.amount(), dec!(100.00));

    let result = hundred - hundred;
    assert_eq!(result.amount(), dec!(0));

    let result = zero * hundred;
    assert_eq!(result.amount(), dec!(0));
}

#[test]
fn test_negative_operations() {
    let negative = Money::<USD>::new(dec!(-50.00)).unwrap();
    let positive = Money::<USD>::new(dec!(100.00)).unwrap();

    let result = negative + positive;
    assert_eq!(result.amount(), dec!(50.00));

    let result = positive + negative;
    assert_eq!(result.amount(), dec!(50.00));

    let result = negative - positive;
    assert_eq!(result.amount(), dec!(-150.00));
}

#[test]
fn test_abs_doesnt_change_original() {
    let money = Money::<USD>::new(dec!(-100.00)).unwrap();
    let abs_money = money.abs();
    assert_eq!(money.amount(), dec!(-100.00));
    assert_eq!(abs_money.amount(), dec!(100.00));
}

#[test]
fn test_min_max_with_equal_values() {
    let money1 = Money::<USD>::new(dec!(100.00)).unwrap();
    let money2 = Money::<USD>::new(dec!(100.00)).unwrap();

    let min_result = money1.min(money2);
    assert_eq!(min_result.amount(), dec!(100.00));

    let max_result = money1.max(money2);
    assert_eq!(max_result.amount(), dec!(100.00));
}

#[test]
fn test_clamp_at_boundaries() {
    let money_at_min = Money::<USD>::new(dec!(100.00)).unwrap();
    let min = Money::<USD>::new(dec!(100.00)).unwrap();
    let max = Money::<USD>::new(dec!(200.00)).unwrap();
    let clamped = money_at_min.clamp(min, max);
    assert_eq!(clamped.amount(), dec!(100.00));

    let money_at_max = Money::<USD>::new(dec!(200.00)).unwrap();
    let min = Money::<USD>::new(dec!(100.00)).unwrap();
    let max = Money::<USD>::new(dec!(200.00)).unwrap();
    let clamped = money_at_max.clamp(min, max);
    assert_eq!(clamped.amount(), dec!(200.00));
}

#[test]
fn test_multiple_separators_in_parsing() {
    let money: Money<USD> = Money::from_str("USD 1,234,567.89").unwrap();
    assert_eq!(money.amount(), dec!(1234567.89));

    // Dot thousands separator requires from_str_dot_thousands
    let money: Money<EUR> = Money::from_str_dot_thousands("EUR 1.234.567,89").unwrap();
    assert_eq!(money.amount(), dec!(1234567.89));
}

#[test]
fn test_currency_mismatch_in_parsing() {
    let money = Money::<EUR>::from_str("USD 1,234,567.89");
    assert!(money.is_err());
    assert_eq!(money.err().unwrap(), MoneyError::CurrencyMismatch);
}

#[test]
fn test_format_preserves_precision() {
    let money = Money::<USD>::new(dec!(0.01)).unwrap();
    let formatted = money.format_code();
    assert!(formatted.contains("0.01"));
}

#[test]
fn test_is_zero_with_very_small_amount() {
    let money = Money::<USD>::new(dec!(0.0001)).unwrap();
    assert!(money.is_zero());
}

#[test]
fn test_is_positive_zero() {
    let money = Money::<USD>::new(dec!(0)).unwrap();
    // Zero is considered positive in Decimal
    assert!(money.is_positive());
    assert!(!money.is_negative());
}

// ==================== Rounding Tests for abs, min, max, clamp ====================

#[test]
fn test_abs_applies_rounding() {
    // Test that abs() applies banker's rounding
    // Create a money with more precision than currency supports
    // USD has 2 decimal places

    // Manually create money with unrounded amount using abs operation
    // This test will fail before the fix and pass after
    let money = Money::<USD>::new(dec!(-100.125)).unwrap();
    // Money::new already rounds to -100.12, so amount is -100.12
    // abs() should maintain rounding: 100.12
    let abs_money = money.abs();
    assert_eq!(
        abs_money.amount(),
        dec!(100.12),
        "abs() should maintain proper rounding"
    );
}

#[test]
fn test_min_applies_rounding() {
    // Test that min() applies banker's rounding
    // USD has 2 decimal places

    let money1 = Money::<USD>::new(dec!(100.125)).unwrap(); // rounds to 100.12
    let money2 = Money::<USD>::new(dec!(100.135)).unwrap(); // rounds to 100.14

    let min_money = money1.min(money2);
    // min should return money1 (100.12) which is already rounded
    assert_eq!(
        min_money.amount(),
        dec!(100.12),
        "min() should maintain proper rounding"
    );
}

#[test]
fn test_max_applies_rounding() {
    // Test that max() applies banker's rounding
    // USD has 2 decimal places

    let money1 = Money::<USD>::new(dec!(100.125)).unwrap(); // rounds to 100.12
    let money2 = Money::<USD>::new(dec!(100.135)).unwrap(); // rounds to 100.14

    let max_money = money1.max(money2);
    // max should return money2 (100.14) which is already rounded
    assert_eq!(
        max_money.amount(),
        dec!(100.14),
        "max() should maintain proper rounding"
    );
}

#[test]
fn test_clamp_applies_rounding() {
    // Test that clamp() applies banker's rounding when clamping to bounds
    // USD has 2 decimal places

    let money = Money::<USD>::new(dec!(50.00)).unwrap();
    // Clamp to a range where the bound has more precision than currency supports
    let min = Money::<USD>::new(dec!(100.125)).unwrap();
    let max = Money::<USD>::new(dec!(200.135)).unwrap();
    let clamped = money.clamp(min, max);
    // Should clamp to 100.125, but Money should round it to 100.12
    assert_eq!(
        clamped.amount(),
        dec!(100.12),
        "clamp() should apply banker's rounding to result"
    );
}

#[test]
fn test_clamp_applies_rounding_upper_bound() {
    // Test that clamp() applies banker's rounding when clamping to upper bound
    // USD has 2 decimal places

    let money = Money::<USD>::new(dec!(300.00)).unwrap();
    // Clamp to a range where the upper bound has more precision
    let min = Money::<USD>::new(dec!(100.00)).unwrap();
    let max = Money::<USD>::new(dec!(200.135)).unwrap();
    let clamped = money.clamp(min, max);
    // Should clamp to 200.135, but Money should round it to 200.14
    assert_eq!(
        clamped.amount(),
        dec!(200.14),
        "clamp() should apply banker's rounding to upper bound"
    );
}

#[test]
fn test_edge_case_very_small_amounts() {
    // Currency implicit via Money::<USD>

    // Test amounts smaller than the currency's precision
    let money1 = Money::<USD>::new(dec!(0.001)).unwrap();
    assert_eq!(money1.amount(), dec!(0.00));

    let money2 = Money::<USD>::new(dec!(0.005)).unwrap();
    assert_eq!(money2.amount(), dec!(0.00)); // Banker's rounding: 0.005 -> 0.00 (to even)

    let money3 = Money::<USD>::new(dec!(0.015)).unwrap();
    assert_eq!(money3.amount(), dec!(0.02)); // Banker's rounding: 0.015 -> 0.02 (to even)
}

#[test]
fn test_edge_case_very_large_amounts() {
    // Currency implicit via Money::<USD>

    // Test large amounts still apply rounding correctly
    let money = Money::<USD>::new(dec!(999999999999999.999)).unwrap();
    assert_eq!(money.amount(), dec!(1000000000000000.00));
}

#[test]
fn test_edge_case_exact_midpoint_sequences() {
    // Test a sequence of midpoint values to ensure consistency
    // 0.015 -> 0.02, 0.025 -> 0.02, 0.035 -> 0.04, 0.045 -> 0.04, 0.055 -> 0.06
    let amounts = vec![
        (dec!(0.015), dec!(0.02)),
        (dec!(0.025), dec!(0.02)),
        (dec!(0.035), dec!(0.04)),
        (dec!(0.045), dec!(0.04)),
        (dec!(0.055), dec!(0.06)),
        (dec!(0.065), dec!(0.06)),
        (dec!(0.075), dec!(0.08)),
        (dec!(0.085), dec!(0.08)),
        (dec!(0.095), dec!(0.10)),
    ];

    for (input, expected) in amounts {
        let money = Money::<USD>::new(input).unwrap();
        assert_eq!(
            money.amount(),
            expected,
            "Failed for input: {}, expected: {}, got: {}",
            input,
            expected,
            money.amount()
        );
    }
}

#[test]
fn test_round_with_custom_decimal_points() {
    // Test round_with method to round to custom decimal points
    // Currency implicit via Money::<USD>
    // Money::new already rounds to 2 decimals (USD precision), so money.amount() is 123.46
    let money = Money::<USD>::new(dec!(123.456789)).unwrap();
    assert_eq!(money.amount(), dec!(123.46)); // Already rounded to currency precision

    // Round to 0 decimal places with different strategies
    let rounded_0_bankers = money.round_with(0, RoundingStrategy::BankersRounding);
    assert_eq!(rounded_0_bankers.amount(), dec!(123));

    let rounded_0_half_up = money.round_with(0, RoundingStrategy::HalfUp);
    assert_eq!(rounded_0_half_up.amount(), dec!(123));

    // round_with can round to more decimal places, but since money is already at 2 decimals,
    // rounding to 4 decimal places just preserves the current 2 decimal value
    let rounded_4 = money.round_with(4, RoundingStrategy::BankersRounding);
    assert_eq!(rounded_4.amount(), dec!(123.46));

    // Test with a value that has fractional parts at multiple levels
    let money2 = Money::<USD>::new(dec!(99.999)).unwrap();
    assert_eq!(money2.amount(), dec!(100.00)); // Rounded to 2 decimals
    let rounded_1 = money2.round_with(1, RoundingStrategy::BankersRounding);
    assert_eq!(rounded_1.amount(), dec!(100.0));
}

#[test]
fn test_custom_formatting() {
    let money = Money::<USD>::new(dec!(100.50)).unwrap();

    // Basic formatting
    // "USD 100.50"
    assert_eq!(money.format("c a"), "USD 100.50");
    // "$100.50"
    assert_eq!(money.format("sa"), "$100.50");
    // "USD 10,050 ¢" (amount in minor units when 'm' is present)
    assert_eq!(money.format("c a m"), "USD 10,050 ¢");
    // adding `n` to positive money will be ignored
    assert_eq!(money.format("c na"), "USD 100.50");
    // Mixing literals with format symbols
    // "Total: $100.50"
    assert_eq!(money.format("Tot\\al: sa"), "Total: $100.50");
    // Escaping format symbols to display them as literals
    // "a=100.50, c=USD"
    assert_eq!(money.format("\\a=a, \\c=c"), "a=100.50, c=USD");
    let negative = Money::<USD>::new(dec!(-50.00)).unwrap();
    // "USD -50.00"
    assert_eq!(negative.format("c na"), "USD -50.00");
    // "-$50.00"
    assert_eq!(negative.format("nsa"), "-$50.00");
    // not specifying the `n` for negative sign will omit the negative sign.
    assert_eq!(negative.format("sa"), "$50.00");

    // negative minor
    assert_eq!(negative.format("sa m"), "$5,000 ¢");
}

// ==================== Money::new() with Various Amount Types ====================

#[test]
fn test_from_amount_with_decimal() {
    let money = Money::<USD>::new(dec!(100.50)).unwrap();
    assert_eq!(money.code(), "USD");
    assert_eq!(money.amount(), dec!(100.50));
}

#[test]
fn test_from_amount_with_f64() {
    let money = Money::<USD>::new(100.50_f64).unwrap();
    assert_eq!(money.code(), "USD");
    assert_eq!(money.amount(), dec!(100.50));
}

#[test]
fn test_from_amount_with_i64() {
    let money = Money::<USD>::new(100_i64).unwrap();
    assert_eq!(money.code(), "USD");
    assert_eq!(money.amount(), dec!(100.00));
}

#[test]
fn test_from_amount_with_i128() {
    let money = Money::<USD>::new(100_i128).unwrap();
    assert_eq!(money.code(), "USD");
    assert_eq!(money.amount(), dec!(100.00));
}

#[test]
fn test_from_amount_with_money_same_currency() {
    let existing_money = Money::<USD>::new(dec!(100.50)).unwrap();
    let money = Money::<USD>::new(existing_money).unwrap();
    assert_eq!(money.code(), "USD");
    assert_eq!(money.amount(), dec!(100.50));
}

#[test]
fn test_from_amount_with_negative_decimal() {
    // Currency implicit via Money::<USD>
    let money = Money::<USD>::new(dec!(-50.25)).unwrap();
    assert_eq!(money.amount(), dec!(-50.25));
}

#[test]
fn test_from_amount_with_negative_i64() {
    // Currency implicit via Money::<USD>
    let money = Money::<USD>::new(-50_i64).unwrap();
    assert_eq!(money.amount(), dec!(-50.00));
}

#[test]
fn test_from_amount_with_zero_decimal() {
    // Currency implicit via Money::<USD>
    let money = Money::<USD>::new(dec!(0)).unwrap();
    assert_eq!(money.amount(), dec!(0));
}

#[test]
fn test_from_amount_with_zero_i128() {
    let money = Money::<EUR>::new(0_i128).unwrap();
    assert_eq!(money.amount(), dec!(0));
}

#[test]
fn test_from_amount_with_large_i128() {
    // Currency implicit via Money::<USD>
    let money = Money::<USD>::new(999_999_999_i128).unwrap();
    assert_eq!(money.amount(), dec!(999999999.00));
}

#[test]
fn test_from_amount_rounding_with_jpy() {
    let money = Money::<JPY>::new(dec!(100.99)).unwrap();
    assert_eq!(money.amount(), dec!(101));
}

#[test]
fn test_from_amount_with_i32() {
    let money = Money::<USD>::new(1234).unwrap();
    assert_eq!(money.amount(), dec!(1234.00));
}

#[test]
fn test_from_amount_rounding_with_bhd() {
    let money = Money::<BHD>::new(dec!(100.9999)).unwrap();
    assert_eq!(money.amount(), dec!(101.000));
}

// ==================== Money::from_minor() Tests ====================

#[test]
fn test_from_minor_amount_usd() {
    let money = Money::<USD>::from_minor(10050).unwrap();
    assert_eq!(money.code(), "USD");
    assert_eq!(money.amount(), dec!(100.50));
}

#[test]
fn test_from_minor_amount_eur() {
    let money = Money::<EUR>::from_minor(5025).unwrap();
    assert_eq!(money.amount(), dec!(50.25));
}

#[test]
fn test_from_minor_amount_jpy() {
    let money = Money::<JPY>::from_minor(100).unwrap();
    assert_eq!(money.amount(), dec!(100));
}

#[test]
fn test_from_minor_amount_bhd() {
    let money = Money::<BHD>::from_minor(100500).unwrap();
    assert_eq!(money.amount(), dec!(100.500));
}

#[test]
fn test_from_minor_amount_zero() {
    let money = Money::<USD>::from_minor(0).unwrap();
    assert_eq!(money.amount(), dec!(0));
}

#[test]
fn test_from_minor_amount_negative() {
    let money = Money::<USD>::from_minor(-5025).unwrap();
    assert_eq!(money.amount(), dec!(-50.25));
}

#[test]
fn test_from_minor_amount_large_value() {
    let money = Money::<USD>::from_minor(999_999_999_99).unwrap();
    assert_eq!(money.amount(), dec!(999999999.99));
}

#[test]
fn test_from_minor_amount_very_small() {
    let money = Money::<USD>::from_minor(1).unwrap();
    assert_eq!(money.amount(), dec!(0.01));
}
