use crate::{number::Ex3Uint, CandidWalletRegisterId, WalletRegisterId};
use candid::{CandidType, Deserialize, Nat};
use ex3_ic_stable_structures::{storable::Bound, Storable};
use ex3_serde::bincode;
use serde::Serialize;

pub type SecretVaultSetting = ServiceScopeSetting;
pub type BalanceVaultSetting = ServiceScopeSetting;
pub type WalletRegistrySetting = ServiceScopeSetting;
pub type CandidSecretVaultSetting = CandidServiceScopeSetting;
pub type CandidBalanceVaultSetting = CandidServiceScopeSetting;
pub type CandidWalletRegistrySetting = CandidServiceScopeSetting;

#[derive(CandidType, Debug, Clone, Deserialize, PartialEq, Eq)]
pub struct CandidServiceScopeSetting {
    pub wallet_start_id: CandidWalletRegisterId,
    pub max_wallet_count: Nat,
}

#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
pub struct ServiceScopeSetting {
    pub wallet_start_id: WalletRegisterId,
    pub max_wallet_count: Ex3Uint,
}

impl From<CandidServiceScopeSetting> for ServiceScopeSetting {
    fn from(setting: CandidServiceScopeSetting) -> Self {
        ServiceScopeSetting {
            wallet_start_id: setting.wallet_start_id.into(),
            max_wallet_count: setting.max_wallet_count.into(),
        }
    }
}

impl From<ServiceScopeSetting> for CandidServiceScopeSetting {
    fn from(setting: ServiceScopeSetting) -> Self {
        CandidServiceScopeSetting {
            wallet_start_id: setting.wallet_start_id.into(),
            max_wallet_count: setting.max_wallet_count.into(),
        }
    }
}

impl Storable for ServiceScopeSetting {
    fn to_bytes(&self) -> std::borrow::Cow<[u8]> {
        bincode::serialize(&self).unwrap().into()
    }

    fn from_bytes(bytes: std::borrow::Cow<[u8]>) -> Self {
        bincode::deserialize(&bytes).expect("deserialize service scope setting failed")
    }

    const BOUND: Bound = Bound::Bounded {
        max_size: 64,
        is_fixed_size: false,
    };
}

#[cfg(test)]
mod tests {

    use super::*;
    #[test]
    fn test_bytes_size() {
        let setting = ServiceScopeSetting {
            wallet_start_id: u128::MAX.into(),
            max_wallet_count: u128::MAX.into(),
        };

        let bytes = setting.to_bytes();
        assert!(bytes.len() < 64);
    }
}
