use orchard::{Bundle, bundle::Authorized, circuit::VerifyingKey, pczt::Unbound};
use rand_core::OsRng;
use zcash_protocol::value::ZatBalance;

pub(super) fn extract_bundle(
    bundle: crate::orchard::Bundle,
) -> Result<Option<Bundle<Unbound, ZatBalance>>, OrchardError> {
    bundle
        .into_parsed()
        .map_err(OrchardError::Parse)?
        .extract()
        .map_err(OrchardError::Extract)
}

pub(super) fn verify_bundle(
    bundle: &Bundle<Authorized, ZatBalance>,
    orchard_vk: Option<&VerifyingKey>,
    sighash: [u8; 32],
) -> Result<(), OrchardError> {
    let mut validator = orchard::bundle::BatchValidator::new();
    let rng = OsRng;

    validator.add_bundle(bundle, sighash);

    if let Some(vk) = orchard_vk {
        if validator.validate(vk, rng) {
            Ok(())
        } else {
            Err(OrchardError::InvalidProof)
        }
    } else {
        let vk = VerifyingKey::build();
        if validator.validate(&vk, rng) {
            Ok(())
        } else {
            Err(OrchardError::InvalidProof)
        }
    }
}

#[derive(Debug)]
pub enum OrchardError {
    Extract(orchard::pczt::TxExtractorError),
    InvalidProof,
    Parse(orchard::pczt::ParseError),
}
