#![allow(unused_assignments)]
use super::*;

#[tokio::test]
async fn test_collateral_fees() -> Result<(), TransportError> {
    let context = TestContext::new().await;
    let solana = &context.solana.clone();

    let admin = TestKeypair::new();
    let owner = context.users[0].key;
    let payer = context.users[1].key;
    let mints = &context.mints[0..2];

    let mango_setup::GroupWithTokens { group, tokens, .. } = mango_setup::GroupWithTokensConfig {
        admin,
        payer,
        mints: mints.to_vec(),
        ..mango_setup::GroupWithTokensConfig::default()
    }
    .create(solana)
    .await;

    // fund the vaults to allow borrowing
    create_funded_account(
        &solana,
        group,
        owner,
        0,
        &context.users[1],
        mints,
        1_000_000,
        0,
    )
    .await;

    let account = create_funded_account(
        &solana,
        group,
        owner,
        1,
        &context.users[1],
        &mints[0..1],
        1_500, // maint: 0.8 * 1500 = 1200
        0,
    )
    .await;

    let empty_account = create_funded_account(
        &solana,
        group,
        owner,
        2,
        &context.users[1],
        &mints[0..0],
        0,
        0,
    )
    .await;

    let hour = 60 * 60;

    send_tx(
        solana,
        GroupEdit {
            group,
            admin,
            options: mango_v4::instruction::GroupEdit {
                collateral_fee_interval_opt: Some(6 * hour),
                ..group_edit_instruction_default()
            },
        },
    )
    .await
    .unwrap();

    send_tx(
        solana,
        TokenEdit {
            group,
            admin,
            mint: mints[0].pubkey,
            fallback_oracle: Pubkey::default(),
            options: mango_v4::instruction::TokenEdit {
                collateral_fee_per_day_opt: Some(0.1),
                ..token_edit_instruction_default()
            },
        },
    )
    .await
    .unwrap();

    send_tx(
        solana,
        TokenEdit {
            group,
            admin,
            mint: mints[1].pubkey,
            fallback_oracle: Pubkey::default(),
            options: mango_v4::instruction::TokenEdit {
                loan_origination_fee_rate_opt: Some(0.0),
                ..token_edit_instruction_default()
            },
        },
    )
    .await
    .unwrap();

    //
    // TEST: It works on empty accounts
    //

    send_tx(
        solana,
        TokenChargeCollateralFeesInstruction {
            account: empty_account,
        },
    )
    .await
    .unwrap();
    let mut last_time = solana.clock_timestamp().await;
    solana.set_clock_timestamp(last_time + 9 * hour).await;

    // send it twice, because the first time will never charge anything
    send_tx(
        solana,
        TokenChargeCollateralFeesInstruction {
            account: empty_account,
        },
    )
    .await
    .unwrap();
    last_time = solana.clock_timestamp().await;

    //
    // TEST: Without borrows, charging collateral fees has no effect
    //

    send_tx(solana, TokenChargeCollateralFeesInstruction { account })
        .await
        .unwrap();
    last_time = solana.clock_timestamp().await;
    solana.set_clock_timestamp(last_time + 9 * hour).await;

    // send it twice, because the first time will never charge anything
    send_tx(solana, TokenChargeCollateralFeesInstruction { account })
        .await
        .unwrap();
    last_time = solana.clock_timestamp().await;

    // no effect
    assert_eq!(
        account_position(solana, account, tokens[0].bank).await,
        1_500
    );

    //
    // TEST: With borrows, there's an effect depending on the time that has passed
    //

    send_tx(
        solana,
        TokenWithdrawInstruction {
            amount: 500, // maint: -1.2 * 500 = -600 (half of 1200)
            allow_borrow: true,
            account,
            owner,
            token_account: context.users[1].token_accounts[1],
            bank_index: 0,
        },
    )
    .await
    .unwrap();

    solana.set_clock_timestamp(last_time + 9 * hour).await;

    send_tx(solana, TokenChargeCollateralFeesInstruction { account })
        .await
        .unwrap();
    last_time = solana.clock_timestamp().await;
    assert_eq_f64!(
        account_position_f64(solana, account, tokens[0].bank).await,
        1500.0 * (1.0 - 0.1 * (9.0 / 24.0) * (600.0 / 1200.0)),
        0.01
    );
    let last_balance = account_position_f64(solana, account, tokens[0].bank).await;

    //
    // TEST: More borrows
    //

    send_tx(
        solana,
        TokenWithdrawInstruction {
            amount: 100, // maint: -1.2 * 600 = -720
            allow_borrow: true,
            account,
            owner,
            token_account: context.users[1].token_accounts[1],
            bank_index: 0,
        },
    )
    .await
    .unwrap();

    solana.set_clock_timestamp(last_time + 7 * hour).await;

    send_tx(solana, TokenChargeCollateralFeesInstruction { account })
        .await
        .unwrap();
    //last_time = solana.clock_timestamp().await;
    assert_eq_f64!(
        account_position_f64(solana, account, tokens[0].bank).await,
        last_balance * (1.0 - 0.1 * (7.0 / 24.0) * (720.0 / (last_balance * 0.8))),
        0.01
    );

    Ok(())
}
