use crate::downloader::{download_from_url, Downloadable};
use crate::errors::ProtoError;
use sha2::{Digest, Sha256};
use starbase_utils::fs::{self, FsError};
use std::io;
use std::path::{Path, PathBuf};
use tracing::debug;
#[async_trait::async_trait]
pub trait Verifiable<'tool>: Send + Sync + Downloadable<'tool> {
    fn get_checksum_path(&self) -> Result<PathBuf, ProtoError>;
    fn get_checksum_url(&self) -> Result<Option<String>, ProtoError>;
    async fn download_checksum(
        &self,
        to_file: &Path,
        from_url: Option<&str>,
    ) -> Result<bool, ProtoError> {
        if to_file.exists() {
            debug!("Checksum already downloaded, continuing");
            return Ok(false);
        }
        let from_url = match from_url {
            Some(url) => Some(url.to_owned()),
            None => self.get_checksum_url()?,
        };
        let Some(from_url) = from_url else {
            return Ok(true);
        };
        debug!(url = from_url, "Attempting to download checksum from URL",);
        download_from_url(&from_url, &to_file).await?;
        debug!("Successfully downloaded checksum");
        Ok(true)
    }
    async fn verify_checksum(
        &self,
        checksum_file: &Path,
        download_file: &Path,
    ) -> Result<bool, ProtoError>;
}
#[tracing::instrument(skip_all)]
pub fn get_sha256_hash_of_file<P: AsRef<Path>>(path: P) -> Result<String, ProtoError> {
    let path = path.as_ref();
    debug!(file = %path.display(), "Calculating SHA256 checksum");
    let mut file = fs::open_file(path)?;
    let mut sha = Sha256::new();
    io::copy(&mut file, &mut sha).map_err(|error| FsError::Read {
        path: path.to_path_buf(),
        error,
    })?;
    let hash = format!("{:x}", sha.finalize());
    debug!(hash, "Calculated hash");
    Ok(hash)
}