use crate::{ham::Ham, CommonOpts};
use anyhow::Result;
use holochain_types::dna::ActionHashB64;
use holochain_types::prelude::AgentPubKeyB64;
use rave_engine::types::entries::InvoiceInput;
use rave_engine::types::return_type::Transaction;
use rave_engine::types::Pieces;
use std::str::FromStr;
use zfuel::fuel::ZFuel;

pub async fn create_spend(
    value: CommonOpts,
    receiver: String,
    amount: String,
    note: Option<String>,
    auto_credit_check: Option<bool>,
) -> Result<()> {
    let agent = Ham::connect(value).await?;

    let input = serde_json::json!({
        "receiver": receiver,
        "amount": amount,
        "note": note,
        "auto_credit_check": auto_credit_check.unwrap_or(true)
    });

    let result: (Transaction, ActionHashB64) = agent
        .zome_call("alliance", "transactor", "create_spend", input)
        .await?;

    println!("===================");
    println!("Spend Created:");
    println!("{:#?}", result);
    println!("===================");

    Ok(())
}

pub async fn create_invoice(
    value: CommonOpts,
    spender: String,
    amount: String,
    note: Option<String>,
) -> Result<()> {
    let agent = Ham::connect(value).await?;
    let mut pieces = Pieces::zero();
    pieces.push_base_unit(ZFuel::from_str(&amount)?);
    let input: InvoiceInput = InvoiceInput {
        spender: AgentPubKeyB64::from_str(&spender)?,
        amount: pieces,
        note: note,
    };

    let result: Transaction = agent
        .zome_call("alliance", "transactor", "create_invoice", input)
        .await?;

    println!("===================");
    println!("Invoice Created:");
    println!("{:#?}", result);
    println!("===================");

    Ok(())
}

pub async fn accept_transaction(
    value: CommonOpts,
    address: String,
    auto_credit_check: Option<bool>,
) -> Result<()> {
    let agent = Ham::connect(value).await?;

    let input = serde_json::json!({
        "address": address,
        "auto_credit_check": auto_credit_check.unwrap_or(true)
    });

    let result: Transaction = agent
        .zome_call("alliance", "transactor", "accept_transaction", input)
        .await?;

    println!("===================");
    println!("Transaction Accepted:");
    println!("{:#?}", result);
    println!("===================");

    Ok(())
}

pub async fn get_parked_spend(value: CommonOpts) -> Result<()> {
    let agent = Ham::connect(value).await?;

    let parked: Vec<Transaction> = agent
        .zome_call("alliance", "transactor", "get_parked_spend", ())
        .await?;

    println!("===================");
    println!("Parked Spends:");
    println!("{:#?}", parked);
    println!("===================");

    Ok(())
}
