use serde::{Deserialize, Serialize};

use crate::{
    bare::GitBare,
    cmd::oid::ObjectId,
    errors::{GitError, GitResult},
};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BlobChunkParam {
    pub path: String,
    pub oid: ObjectId,
    pub size: usize,
    pub offset: usize,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BlobChunk {
    pub param: BlobChunkParam,
    pub chunk: Vec<u8>,
}

impl GitBare {
    pub fn blob_chunk(&self, param: BlobChunkParam) -> GitResult<BlobChunk> {
        let repo = self.gix_repo()?;
        let gix_id: gix::hash::ObjectId = (&param.oid).try_into()?;

        let blob = repo.find_blob(gix_id).map_err(|_| {
            GitError::ObjectNotFound(param.oid.as_str().to_string())
        })?;

        let blob_bytes = blob.data.clone();
        let end = param.offset + param.size;
        if end > blob_bytes.len() {
            return Err(GitError::ParseError(format!(
                "chunk offset+size ({}) exceeds blob length ({})",
                end,
                blob_bytes.len()
            )));
        }

        let chunk = blob_bytes[param.offset..end].to_vec();

        Ok(BlobChunk { param, chunk })
    }
}
