use clap::Parser;

use libpijul::changestore::ChangeStore;
use libpijul::*;
use pijul_repository::*;

use crate::commands::common_opts::RepoPath;
use crate::commands::get_channel;

#[derive(Parser, Debug)]
pub struct Change {
    #[clap(flatten)]
    base: RepoPath,
    /// The hash of the change to show, or an unambiguous prefix thereof
    #[clap(value_name = "HASH")]
    hash: Option<String>,
}

impl Change {
    pub fn run(self) -> Result<(), anyhow::Error> {
        let repo = Repository::find_root(self.base.repo_path())?;
        let txn = repo.pristine.txn_begin()?;
        let changes = repo.changes;

        let hash = if let Some(hash) = self.hash {
            if let Some(h) = Hash::from_base32(hash.as_bytes()) {
                h
            } else {
                txn.hash_from_prefix(&hash)?.0
            }
        } else {
            let (channel_name, _) = get_channel(None, &txn);
            let Some(channel) = txn.load_channel(channel_name)? else {
                return Ok(());
            };
            let channel = channel.read();
            if let Some(h) = txn.reverse_log(&*channel, None)?.next() {
                (h?.1).0.into()
            } else {
                return Ok(());
            }
        };
        let change = changes.get_change(&hash)?;
        let colors = super::diff::is_colored(repo.config.pager.as_ref());
        change.write(
            &changes,
            Some(hash),
            true,
            super::diff::Colored {
                w: termcolor::StandardStream::stdout(termcolor::ColorChoice::Auto),
                colors,
            },
        )?;
        Ok(())
    }
}