use std::str::FromStr;
use ex3_node_error::OtherError;
use ex3_node_types::chain::Chain;
use ex3_timestamp::TimeInNs;
use num_bigint::BigUint;
use num_traits::Num;
use crate::{PayloadDecoder, Result};
impl PayloadDecoder {
    pub fn decode_to_withdrawal(payload: &[u8]) -> Result<ex3_node_types::transaction::Withdrawal> {
        let payload_str = String::from_utf8(payload.as_ref().to_vec()).expect("should success");
        let hexes = payload_str.split('|').collect::<Vec<&str>>();
        let err = OtherError::new("Invalid payload");
        if hexes.len() != 7 {
            return Err(err.clone().into());
        }
        let sign_chain = BigUint::from_str_radix(hexes[0], 16).map_err(|_| err.clone())?;
        let chain = BigUint::from_str_radix(hexes[1], 16).map_err(|_| err.clone())?;
        let network = u8::from_str_radix(hexes[2], 16).map_err(|_| err.clone())?;
        let to_address: String = hexes[3].to_string();
        let asset_id = BigUint::from_str_radix(hexes[4], 16).map_err(|_| err.clone())?;
        let amount = BigUint::from_str(hexes[5]).map_err(|_| err.clone())?;
        let fee = BigUint::from_str(hexes[6]).map_err(|_| err.clone())?;
        let withdrawal = ex3_node_types::transaction::Withdrawal {
            sign_chain: sign_chain.into(),
            chain: chain.into(),
            network,
            to: to_address,
            asset_id: asset_id.into(),
            amount: amount.into(),
            fee: fee.into(),
        };
        Ok(withdrawal)
    }
    pub fn decode_to_force_withdrawal(
        payload: &[u8],
    ) -> Result<ex3_node_types::transaction::ForceWithdrawal> {
        let payload_str = String::from_utf8(payload.as_ref().to_vec()).expect("should success");
        let hexes = payload_str.split('|').collect::<Vec<&str>>();
        let err = OtherError::new("Invalid payload");
        if hexes.len() != 8 {
            return Err(err.clone().into());
        }
        let sign_chain_type = BigUint::from_str_radix(hexes[0], 16).map_err(|_| err.clone())?;
        let chain_type = BigUint::from_str_radix(hexes[1], 16).map_err(|_| err.clone())?;
        let network = BigUint::from_str_radix(hexes[1], 16).map_err(|_| err.clone())?;
        let to_address: String = String::from_utf8(hex::decode(hexes[2]).map_err(|_| err.clone())?)
            .map_err(|_| err.clone())?;
        let asset_id = BigUint::from_str_radix(hexes[3], 16).map_err(|_| err.clone())?;
        let amount = BigUint::from_str(hexes[4]).map_err(|_| err.clone())?;
        let fee = BigUint::from_str(hexes[5]).map_err(|_| err.clone())?;
        let timestamp = u64::from_str_radix(hexes[6], 16).map_err(|_| err.clone())?;
        let force_withdrawal = ex3_node_types::transaction::ForceWithdrawal {
            sign_chain_type: sign_chain_type.into(),
            chain: Chain {
                r#type: chain_type.into(),
                network,
            },
            to: to_address,
            asset_id: asset_id.into(),
            amount: amount.into(),
            fee: fee.into(),
            timestamp: TimeInNs(timestamp),
        };
        Ok(force_withdrawal)
    }
}