use clap::Parser;

use obnam::{
    config::Config,
    id::{Id, IdError, IdFactory},
};

use super::{Args, Leaf, ObnamError};

/// Generate a new chunk ID and encode it.
#[derive(Debug, Parser)]
pub struct Generate {}

impl Leaf for Generate {
    type Error = IdCmdError;

    fn run(&self, _args: &Args, _config: &Config) -> Result<(), Self::Error> {
        let mut factory = IdFactory::default();
        let id = factory.id();
        println!("{id}");
        Ok(())
    }
}

/// Decode a chunk ID into an integer.
#[derive(Debug, Parser)]
pub struct Decode {
    /// The encoded chunk ID.
    encoded: String,
}

impl Leaf for Decode {
    type Error = IdCmdError;

    fn run(&self, _args: &Args, _config: &Config) -> Result<(), Self::Error> {
        let id = Id::try_from(&self.encoded).map_err(IdCmdError::Decode)?;
        println!("{}", id.as_u128());
        Ok(())
    }
}

#[derive(Debug, thiserror::Error)]
pub enum IdCmdError {
    #[error("failed to decode chunk ID")]
    Decode(#[source] IdError),
}

impl From<IdCmdError> for ObnamError {
    fn from(value: IdCmdError) -> Self {
        ObnamError::Id(value)
    }
}
