//! Shared argument types for power management commands.

use std::fmt;

use anyhow::{Error, bail};

use crate::cli::common;
use crate::cli::http_client::MantaClient;
use crate::cli::output::action_result;
use manta_shared::common::app_context::AppContext;

/// The three power operations supported by the backend.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PowerAction {
  /// Power nodes on.
  On,
  /// Power nodes off.
  Off,
  /// Power-cycle (reset) nodes.
  Reset,
}

impl fmt::Display for PowerAction {
  fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    match self {
      PowerAction::On => write!(f, "power on"),
      PowerAction::Off => write!(f, "power off"),
      PowerAction::Reset => write!(f, "power reset"),
    }
  }
}

impl PowerAction {
  /// Human-readable confirmation prompt fragment.
  fn confirmation_text(&self) -> &'static str {
    match self {
      PowerAction::On => {
        "The nodes above will be powered on. \
         Please confirm to proceed?"
      }
      PowerAction::Off => {
        "The nodes above will be powered off. \
         Please confirm to proceed?"
      }
      PowerAction::Reset => {
        "The nodes above will restart. \
         Please confirm to proceed?"
      }
    }
  }
}

/// Execute a power action against a list of nodes resolved
/// from a hosts expression.
pub async fn exec_nodes(
  ctx: &AppContext<'_>,
  action: PowerAction,
  hosts_expression: &str,
  force: bool,
  assume_yes: bool,
  output: &str,
  token: &str,
) -> Result<(), Error> {
  let action_str = match action {
    PowerAction::On => "on",
    PowerAction::Off => "off",
    PowerAction::Reset => "reset",
  };

  let server_url = ctx.manta_server_url;
  // Interactive context printed before the confirm prompt; intentionally
  // plain stdout so it doesn't get wrapped in a JSON envelope.
  println!("Nodes expression: {hosts_expression}");
  if !common::user_interaction::confirm(action.confirmation_text(), assume_yes)
  {
    bail!("Operation cancelled by user");
  }
  let result = MantaClient::new(server_url, ctx.site_name)?
    .power(token, action_str, hosts_expression, "nodes", force)
    .await?;
  action_result::print_with_data(
    &format!("Power {action_str} requested on nodes."),
    &result,
    Some(output),
  )?;
  Ok(())
}

/// Execute a power action against all nodes in an HSM group
/// (cluster).
pub async fn exec_cluster(
  ctx: &AppContext<'_>,
  action: PowerAction,
  hsm_group_name_arg: &str,
  force: bool,
  assume_yes: bool,
  output: &str,
  token: &str,
) -> Result<(), Error> {
  let action_str = match action {
    PowerAction::On => "on",
    PowerAction::Off => "off",
    PowerAction::Reset => "reset",
  };

  let server_url = ctx.manta_server_url;
  // Interactive context printed before the confirm prompt; intentionally
  // plain stdout so it doesn't get wrapped in a JSON envelope.
  println!("Cluster: {hsm_group_name_arg}");
  if !common::user_interaction::confirm(action.confirmation_text(), assume_yes)
  {
    bail!("Operation cancelled by user");
  }
  let result = MantaClient::new(server_url, ctx.site_name)?
    .power(token, action_str, hsm_group_name_arg, "cluster", force)
    .await?;
  action_result::print_with_data(
    &format!("Power {action_str} requested on cluster."),
    &result,
    Some(output),
  )?;
  Ok(())
}
