use std::fmt::Display;

use candid::CandidType;
use ex3_serde::bincode;
use ex3_timestamp::TimeInNs;
use ic_stable_structures::{storable::Bound, Storable};
use serde::{Deserialize, Serialize};
use serde_bytes::ByteBuf;

use crate::{
    AssetAmount, AssetId, BlockHeight, CandidAssetAmount, CandidAssetId, CandidBlockHeight,
    CandidDepositId, CandidWalletRegisterId, DepositId, WalletRegisterId,
};

/// AssetAccountBinding
#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize, PartialOrd, Ord)]
pub struct AssetAccountBinding {
    /// The main wallet id
    pub main: WalletRegisterId,

    /// The asset wallet id
    pub asset: WalletRegisterId,

    /// The initial wallet id
    ///
    /// Note: this is the wallet id that is used to create the asset account binding tx,
    ///       So it is  main wallet id or asset wallet id
    pub initial: WalletRegisterId,

    /// The initial wallet signature
    pub initial_signature: ByteBuf,

    /// Tx timestamp
    pub timestamp: TimeInNs,
}

impl Display for AssetAccountBinding {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "{}:{}:{}:{}:{}",
            self.main,
            self.asset,
            self.initial,
            hex::encode(self.initial_signature.as_ref()),
            self.timestamp,
        )
    }
}

/// Asset Account Unbinding
#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize, PartialOrd, Ord)]
pub struct AssetAccountUnbinding {
    /// The main wallet id
    pub main: WalletRegisterId,

    /// The asset wallet id
    pub asset: WalletRegisterId,
}

impl Display for AssetAccountUnbinding {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}:{}", self.main, self.asset,)
    }
}
