use ex3_serde::{bincode, cbor};
use num_bigint::BigUint;

use crate::market::{SpotMarketTradingFee, SpotMarketTradingSettings, SpotOrderPriceLimitation};
use crate::transaction::{
    RegisterSpotMarket, UpdateMarketFeeTo, UpdateMarketInitialFeeTo, UpdateSpotMarketFee,
    UpdateSpotMarketInitialFee, UpdateSpotMarketTradingSettings,
};
use crate::{AssetAmount, AssetId, MarketId, WalletRegisterId};

#[test]
fn test_update_market_fee_to_serde() {
    let update_market_fee_to = UpdateMarketFeeTo {
        market_id: MarketId::from(1u32),
        fee_to: WalletRegisterId::from(1u32),
    };

    // bincode
    let bytes = bincode::serialize(&update_market_fee_to).unwrap();
    let update_market_fee_to_deserialized: UpdateMarketFeeTo =
        bincode::deserialize(&bytes).unwrap();
    assert_eq!(update_market_fee_to, update_market_fee_to_deserialized);

    // cbor
    let bytes = cbor::serialize(&update_market_fee_to).unwrap();
    let update_market_fee_to_deserialized: UpdateMarketFeeTo = cbor::deserialize(&bytes).unwrap();
    assert_eq!(update_market_fee_to, update_market_fee_to_deserialized);
}

#[test]
fn test_register_market_serde() {
    let register_market = RegisterSpotMarket {
        base_asset_id: AssetId::from(1u32),
        base_asset_quantity: AssetAmount::from(100u32),
        quote_asset_id: AssetId::from(2u32),
        quote_asset_quantity: AssetAmount::from(200u32),
        trading_settings: SpotMarketTradingSettings {
            price_max_decimal: 8,
            volume_max_decimal: 8,
            min_order_amount: AssetAmount::from(300u32),
            min_order_volume: AssetAmount::from(400u32),
            price_limitation: SpotOrderPriceLimitation {
                bid_price_rate_cap: BigUint::from(100u32),
                ask_price_rate_floor: BigUint::from(100u32),
                rate_decimal: 8,
            },
        },
    };

    // bincode
    let bytes = bincode::serialize(&register_market).unwrap();
    let register_market_deserialized: RegisterSpotMarket = bincode::deserialize(&bytes).unwrap();
    assert_eq!(register_market, register_market_deserialized);

    // cbor
    let bytes = cbor::serialize(&register_market).unwrap();
    let register_market_deserialized: RegisterSpotMarket = cbor::deserialize(&bytes).unwrap();
    assert_eq!(register_market, register_market_deserialized);
}

#[test]
fn test_update_market_settings_serde() {
    let update_market_settings = UpdateSpotMarketTradingSettings {
        market_id: MarketId::from(1u32),
        trading_settings: SpotMarketTradingSettings {
            price_max_decimal: 8,
            volume_max_decimal: 8,
            min_order_amount: AssetAmount::from(100u32),
            min_order_volume: AssetAmount::from(100u32),
            price_limitation: SpotOrderPriceLimitation {
                bid_price_rate_cap: BigUint::from(100u32),
                ask_price_rate_floor: BigUint::from(100u32),
                rate_decimal: 8,
            },
        },
    };

    // bincode
    let bytes = bincode::serialize(&update_market_settings).unwrap();
    let update_market_settings_deserialized: UpdateSpotMarketTradingSettings =
        bincode::deserialize(&bytes).unwrap();
    assert_eq!(update_market_settings, update_market_settings_deserialized);

    // cbor
    let bytes = cbor::serialize(&update_market_settings).unwrap();
    let update_market_settings_deserialized: UpdateSpotMarketTradingSettings =
        cbor::deserialize(&bytes).unwrap();
    assert_eq!(update_market_settings, update_market_settings_deserialized);
}

#[test]
fn test_update_global_market_fee_to_serde() {
    let update_global_market_fee_to = UpdateMarketInitialFeeTo {
        fee_to: WalletRegisterId::from(1u32),
    };

    // bincode
    let bytes = bincode::serialize(&update_global_market_fee_to).unwrap();
    let update_global_market_fee_to_deserialized: UpdateMarketInitialFeeTo =
        bincode::deserialize(&bytes).unwrap();
    assert_eq!(
        update_global_market_fee_to,
        update_global_market_fee_to_deserialized
    );

    // cbor
    let bytes = cbor::serialize(&update_global_market_fee_to).unwrap();
    let update_global_market_fee_to_deserialized: UpdateMarketInitialFeeTo =
        cbor::deserialize(&bytes).unwrap();
    assert_eq!(
        update_global_market_fee_to,
        update_global_market_fee_to_deserialized
    );
}

#[test]
fn test_update_global_market_fee_serde() {
    let update_global_market_fee = UpdateSpotMarketInitialFee {
        fee: SpotMarketTradingFee {
            taker_fee: BigUint::from(100u32),
            maker_fee: BigUint::from(200u32),
            fee_decimal: 8,
            amm_v2_fee_taking_ratio: BigUint::from(300u32),
        },
    };

    // bincode
    let bytes = bincode::serialize(&update_global_market_fee).unwrap();
    let update_global_market_fee_deserialized: UpdateSpotMarketInitialFee =
        bincode::deserialize(&bytes).unwrap();
    assert_eq!(
        update_global_market_fee,
        update_global_market_fee_deserialized
    );

    // cbor
    let bytes = cbor::serialize(&update_global_market_fee).unwrap();
    let update_global_market_fee_deserialized: UpdateSpotMarketInitialFee =
        cbor::deserialize(&bytes).unwrap();
    assert_eq!(
        update_global_market_fee,
        update_global_market_fee_deserialized
    );
}

#[test]
fn test_update_market_fee_serde() {
    let update_market_fee = UpdateSpotMarketFee {
        market_id: MarketId::from(1u32),
        fee: SpotMarketTradingFee {
            taker_fee: BigUint::from(100u32),
            maker_fee: BigUint::from(200u32),
            fee_decimal: 8,
            amm_v2_fee_taking_ratio: BigUint::from(200u32),
        },
    };

    // bincode
    let bytes = bincode::serialize(&update_market_fee).unwrap();
    let update_market_fee_deserialized: UpdateSpotMarketFee = bincode::deserialize(&bytes).unwrap();
    assert_eq!(update_market_fee, update_market_fee_deserialized);

    // cbor
    let bytes = cbor::serialize(&update_market_fee).unwrap();
    let update_market_fee_deserialized: UpdateSpotMarketFee = cbor::deserialize(&bytes).unwrap();
    assert_eq!(update_market_fee, update_market_fee_deserialized);
}
