use num_bigint::BigUint;
use num_traits::ToPrimitive;
use serde::{Deserialize, Serialize};

use crate::impl_from_uint_for_enum;

/// Transaction type.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
pub enum TransactionType {
    /// Wallet register.
    WalletRegister = 100,

    /// Deposit.
    Deposit = 200,

    /// Withdrawal.
    Withdrawal = 201,

    /// Transfer.
    Transfer = 300,

    /// Reset main secret.
    ResetMainSecret = 400,

    /// Create API secret.
    CreateApiSecret = 401,

    /// Destroy API secret.
    DestroyApiSecret = 402,

    /// Create spot order.
    CreateSpotOrder = 500,

    /// Cancel spot order.
    CancelSpotOrder = 501,

    /// Add spot liquidity.
    AddAmmV2Liquidity = 600,

    /// Remove spot liquidity.
    RemoveAmmV2Liquidity = 601,
}

impl From<BigUint> for TransactionType {
    fn from(value: BigUint) -> Self {
        match value.to_u64().unwrap() {
            100 => TransactionType::WalletRegister,
            200 => TransactionType::Deposit,
            201 => TransactionType::Withdrawal,
            300 => TransactionType::Transfer,
            400 => TransactionType::ResetMainSecret,
            401 => TransactionType::CreateApiSecret,
            402 => TransactionType::DestroyApiSecret,
            500 => TransactionType::CreateSpotOrder,
            501 => TransactionType::CancelSpotOrder,
            600 => TransactionType::AddAmmV2Liquidity,
            601 => TransactionType::RemoveAmmV2Liquidity,
            _ => panic!("Invalid transaction type"),
        }
    }
}

impl Into<BigUint> for TransactionType {
    fn into(self) -> BigUint {
        BigUint::from(self as u128)
    }
}

impl_from_uint_for_enum!(TransactionType, u32, u64, u128);
