use crate::error::{TrazaeoError, TrazaeoResult};
use crate::utils::Hash;
use std::path::Path;

#[cfg(feature = "python-proof-log-rpc")]
pub(crate) use crate::adaptors::PublicRpcSolanaProofLogAdaptor;
pub(crate) use crate::adaptors::{
    DeterministicS3StorageAdaptor, ProofLogAdaptor, S3PutRequest, SolanaProofLogAdaptor,
    StorageAdaptor, StoredObject,
};
pub(crate) use crate::bootstrap::{SourceFileEntry, SourceManifest};
pub(crate) use crate::checkpoint::{CheckpointArtifact, CheckpointManifest};
#[cfg(feature = "bao-range-proofs")]
pub(crate) use crate::content::{
    attach_bao_outboard, build_bao_range_proof_package, generate_bao_outboard,
    verify_bao_range_proof_package,
};
pub(crate) use crate::content::{ContentDescriptor, RangeProofPackage};
pub(crate) use crate::dataset_workflows::{
    build_dataset_bootstrap_bundle as build_dataset_bootstrap_bundle_model,
    build_dataset_delivery_proof_package as build_dataset_delivery_proof_package_model,
    build_dataset_incremental_bundle as build_dataset_incremental_bundle_model,
    DatasetBootstrapWorkflowInput, DatasetIncrementalWorkflowInput, DatasetProvenanceBundle,
};
pub(crate) use crate::delivery_proofs::{DeliveryProofPackage, DeliveryProofVerificationResult};
pub(crate) use crate::envelope::{
    make_attestation as make_envelope_attestation, Attestation, CaptureEnvelope, PublishEnvelope,
    TransformEnvelope,
};
pub(crate) use crate::proof_log::{ProofLogCommitment, ProofLogPublishResult};
pub(crate) use crate::solana::{SolanaClient, SolanaConfig};
pub(crate) use crate::verification::VerificationMode;
pub(crate) use crate::{
    bootstrap::{
        compute_source_root_hash as compute_source_root_hash_model,
        validate_source_manifest as validate_source_manifest_model,
    },
    solana::{
        cluster_name as solana_cluster_name_model, init_solana_client as init_solana_client_model,
        program_id as solana_program_id_model,
    },
    zero_copy::hash_file_content_descriptor_zero_copy,
};
pub(crate) use crate::{
    capture::{
        build_capture_envelope as build_capture_envelope_model, CaptureSessionInput,
        CapturedSegment,
    },
    checkpoint::build_checkpoint_manifest as build_checkpoint_manifest_model,
    content::build_full_root_proof_package as build_full_root_proof_package_model,
    delivery_proofs::{
        build_delivery_proof_package as build_delivery_proof_package_model,
        verify_delivery_proof_package_against_root as verify_delivery_proof_package_against_root_model,
        verify_delivery_proof_package_with_report as verify_delivery_proof_package_with_report_model,
    },
    hashing::{
        blake3_hash_with_threads as blake3_hash_with_threads_model, hash_file_streaming_root,
    },
    publish_pipeline::{build_publish_envelope as build_publish_envelope_model, PublishInput},
    transform_pipeline::{
        build_transform_envelope as build_transform_envelope_model, TransformStageInput,
    },
    trust::TrustPolicy,
    verification::verify_publish_envelope as verify_publish_envelope_model,
};

pub(crate) fn make_attestation(
    signer_id: &str,
    signing_key_hex: &str,
    signed_at: &str,
    payload: &[u8],
) -> TrazaeoResult<Attestation> {
    make_envelope_attestation(signer_id, signing_key_hex, signed_at, payload)
}

pub(crate) fn build_capture_envelope(
    input: &CaptureSessionInput,
    messages: &[CapturedSegment],
    attestation: Attestation,
) -> crate::envelope::CaptureEnvelope {
    build_capture_envelope_model(input, messages, attestation)
}

pub(crate) fn build_transform_envelope(
    input: &TransformStageInput,
    attestation: Attestation,
) -> crate::envelope::TransformEnvelope {
    build_transform_envelope_model(input, attestation)
}

pub(crate) fn build_publish_envelope(
    input: &PublishInput,
    attestation: Attestation,
) -> PublishEnvelope {
    build_publish_envelope_model(input, attestation)
}

pub(crate) fn verify_publish_envelope(
    envelope: &PublishEnvelope,
    mode: VerificationMode,
    trust: &TrustPolicy,
) -> crate::verification::VerificationReport {
    verify_publish_envelope_model(envelope, mode, trust)
}

pub(crate) fn compute_source_root_hash(source_files: &[SourceFileEntry]) -> Hash {
    compute_source_root_hash_model(source_files)
}

pub(crate) fn validate_source_manifest(manifest: &SourceManifest) -> TrazaeoResult<()> {
    validate_source_manifest_model(manifest)
}

pub(crate) fn init_solana_client(config: &SolanaConfig) -> SolanaClient {
    init_solana_client_model(config)
}

pub(crate) fn solana_cluster_name(client: &SolanaClient) -> String {
    solana_cluster_name_model(client)
}

pub(crate) fn solana_program_id(client: &SolanaClient) -> String {
    solana_program_id_model(client)
}

pub(crate) fn build_checkpoint_manifest(
    checkpoint_id: &str,
    checkpoint_time_window: &str,
    prior_checkpoint_ref: Option<&str>,
    checkpoint_signature_bundle: Vec<String>,
    published_artifacts: Vec<CheckpointArtifact>,
    lineage_refs: Vec<String>,
) -> CheckpointManifest {
    build_checkpoint_manifest_model(
        checkpoint_id,
        checkpoint_time_window,
        prior_checkpoint_ref,
        checkpoint_signature_bundle,
        published_artifacts,
        lineage_refs,
    )
}

pub(crate) fn build_full_root_proof_package(
    descriptor: &ContentDescriptor,
) -> TrazaeoResult<RangeProofPackage> {
    build_full_root_proof_package_model(descriptor)
}

pub(crate) fn verify_full_root_proof_package(
    package: &RangeProofPackage,
    bytes: &[u8],
) -> TrazaeoResult<Vec<u8>> {
    crate::content::verify_full_root_proof_package(package, bytes)
}

pub(crate) fn build_delivery_proof_package(
    range_proof_package: &RangeProofPackage,
    lineage_envelopes: Vec<String>,
    checkpoint_manifest: CheckpointManifest,
    signature_bundle: Vec<String>,
) -> TrazaeoResult<DeliveryProofPackage> {
    build_delivery_proof_package_model(
        range_proof_package,
        lineage_envelopes,
        checkpoint_manifest,
        signature_bundle,
    )
}

pub(crate) fn build_dataset_bootstrap_bundle(
    input: DatasetBootstrapWorkflowInput,
) -> TrazaeoResult<DatasetProvenanceBundle> {
    build_dataset_bootstrap_bundle_model(input)
}

pub(crate) fn build_dataset_incremental_bundle(
    input: DatasetIncrementalWorkflowInput,
) -> TrazaeoResult<DatasetProvenanceBundle> {
    build_dataset_incremental_bundle_model(input)
}

pub(crate) fn build_dataset_delivery_proof_package(
    bundle: &DatasetProvenanceBundle,
    range_proof_package: &RangeProofPackage,
) -> TrazaeoResult<DeliveryProofPackage> {
    build_dataset_delivery_proof_package_model(bundle, range_proof_package)
}

pub(crate) fn verify_delivery_proof_package_against_root(
    package: &DeliveryProofPackage,
    artifact_bytes: Option<&[u8]>,
    trusted_checkpoint_log_root: Option<&Hash>,
) -> TrazaeoResult<Vec<u8>> {
    verify_delivery_proof_package_against_root_model(
        package,
        artifact_bytes,
        trusted_checkpoint_log_root,
    )
}

pub(crate) fn verify_delivery_proof_package_with_report(
    package: &DeliveryProofPackage,
    artifact_bytes: Option<&[u8]>,
    trusted_checkpoint_log_root: Option<&Hash>,
) -> DeliveryProofVerificationResult {
    verify_delivery_proof_package_with_report_model(
        package,
        artifact_bytes,
        trusted_checkpoint_log_root,
    )
}

pub(crate) fn blake3_hash_with_threads(data: &[u8], num_threads: usize) -> Hash {
    blake3_hash_with_threads_model(data, num_threads)
}

pub(crate) fn content_descriptor_for_path(
    path: &Path,
    chunk_size: usize,
    threads: usize,
    artifact_id: &str,
    media_type: &str,
    created_at: &str,
) -> TrazaeoResult<ContentDescriptor> {
    hash_file_content_descriptor_zero_copy(
        path,
        &crate::chunker::ChunkingConfig { chunk_size },
        threads,
        artifact_id,
        media_type,
        created_at,
    )
    .map_err(|err| TrazaeoError::io("build content descriptor", format!("{err}")))
}

pub(crate) fn io_err(context: &'static str, details: impl Into<String>) -> TrazaeoError {
    TrazaeoError::io(context, details)
}
