use anyhow::Result;
use std::io::Read;
use crate::types::{DirEntry, FileChange};

pub trait ContextStore {
    /// Initialize a new repository for the request
    fn init_repo(&self, req_id: &str) -> Result<()>;

    /// Read file content. Transparently handles BlobRef redirection.
    fn read_file(&self, req_id: &str, commit_hash: &str, path: &str) -> Result<Box<dyn Read + Send>>;

    /// List directory contents
    fn list_dir(&self, req_id: &str, commit_hash: &str, path: &str) -> Result<Vec<DirEntry>>;

    /// Get changes between two commits
    fn diff(&self, req_id: &str, from_commit: &str, to_commit: &str) -> Result<Vec<FileChange>>;
    
    /// Three-way merge (In-Memory), returns new Tree OID
    fn merge_trees(&self, req_id: &str, base: &str, ours: &str, theirs: &str) -> Result<String>;

    /// Smart merge two commits, automatically finding the best common ancestor.
    /// Returns the OID of the new merge commit.
    fn merge_commits(&self, req_id: &str, our_commit: &str, their_commit: &str) -> Result<String>;
    
    /// Start a write transaction
    fn begin_transaction(&self, req_id: &str, base_commit: &str) -> Result<Box<dyn Transaction>>;
}

pub trait Transaction {
    /// Write file content
    fn write(&mut self, path: &str, content: &[u8]) -> Result<()>;

    /// Remove file
    fn remove(&mut self, path: &str) -> Result<()>;

    /// Commit changes
    fn commit(self: Box<Self>, message: &str, author: &str) -> Result<String>;
}

