use std::path::Path;

use clap::Parser;

use pijul_core::changestore::ChangeStore;
use pijul_core::*;

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 repository_path(&mut self) -> Option<&Path> {
        self.base.repo_path()
    }

    pub fn run(mut self, config: &pijul_config::Config) -> Result<(), anyhow::Error> {
        let repo = self.base.find_root()?;
        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.parse()?)? 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(config);
        change.write(
            &changes,
            Some(hash),
            true,
            super::diff::Colored {
                w: termcolor::StandardStream::stdout(termcolor::ColorChoice::Auto),
                colors,
            },
        )?;
        Ok(())
    }
}
