use clap::Parser;
use serde::Serialize;

use super::{AmbientError, Config, Leaf};
use ambient_ci::{
    action::{PostPlanAction, PrePlanAction, UnsafeAction},
    runlog::RunLog,
};

/// Show available actions to the user.
#[derive(Debug, Parser)]
pub struct Actions {
    #[clap(long)]
    oneline: bool,
}

impl Leaf for Actions {
    fn run(&self, _config: &Config, _runlog: &mut RunLog) -> Result<(), AmbientError> {
        #[derive(Serialize)]
        struct Actions {
            pre_actions: Vec<&'static str>,
            actions: Vec<&'static str>,
            post_actions: Vec<&'static str>,
        }

        let mut actions = Actions {
            pre_actions: PrePlanAction::names().to_vec(),
            actions: UnsafeAction::names().to_vec(),
            post_actions: PostPlanAction::names().to_vec(),
        };

        actions.pre_actions.sort();
        actions.actions.sort();
        actions.post_actions.sort();

        let json = if self.oneline {
            serde_json::to_string(&actions).map_err(ActionError::ToJson)?
        } else {
            serde_json::to_string_pretty(&actions).map_err(ActionError::ToJson)?
        };

        println!("{json}");

        Ok(())
    }
}

#[derive(Debug, thiserror::Error)]
pub enum ActionError {
    #[error("failed to serialize action list to JSON")]
    ToJson(#[source] serde_json::Error),
}
