use std::path::PathBuf;

use serde::{Deserialize, Serialize};

use crate::{
    action::{ActionError, Context},
    action_impl::ActionImpl,
    runlog::RunLogSource,
};

/// Print working directory.
///
/// This is meant for debugging plans. It can be used in pre- and post-plans,
/// where the `shell` action can't be.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Pwd;

impl ActionImpl for Pwd {
    fn execute(&self, context: &mut Context) -> Result<(), ActionError> {
        let path = context.source_dir();
        let path = path
            .canonicalize()
            .map_err(|err| PwdError::Canonicalize(path.to_path_buf(), err))?;
        context
            .runlog()
            .debug(RunLogSource::PostPlan, format!("cwd: {}", path.display()));
        Ok(())
    }
}

/// Errors from the Pwd action.
#[derive(Debug, thiserror::Error)]
pub enum PwdError {
    /// Can't convert a path into an absolute one.
    #[error("failed to make path absolute: {0}")]
    Canonicalize(PathBuf, #[source] std::io::Error),
}

impl From<PwdError> for ActionError {
    fn from(value: PwdError) -> Self {
        Self::Pwd(value)
    }
}
