//! Alarm CRUD commands — `:alarm-create` and `:alarm-delete`. Both
//! route through `AwsClient::put_env_metric_alarm` /
//! `AwsClient::delete_alarms` and reuse the `AppMsg::AlarmOp` plumbing
//! so the pending pill closes + a toast fires on completion.
//!
//! Eighth slice of the `execute_command` split. Same parent-module
//! visibility pattern as the other `cmd_*` sub-modules.

use super::{alarm_kind_to_metric, flatten_err, write_audit_line, App, AppMsg};

impl App {
    /// `:alarm-create NAME KIND THRESHOLD [op]` — KIND maps to one
    /// of the env-scoped metrics we already chart (health / 4xx
    /// / 5xx / latency). Operator can override the comparison
    /// operator as a 4th arg; period defaults to 300s and 1
    /// evaluation period for a 5-min trigger.
    pub(crate) fn cmd_alarm_create(&mut self, rest: &[&str]) {
        let (name, kind, threshold_raw, op_override) = match (
            rest.first().copied(),
            rest.get(1).copied(),
            rest.get(2).copied(),
            rest.get(3).copied(),
        ) {
            (Some(n), Some(k), Some(t), op) => (n, k, t, op),
            _ => {
                self.error_message = Some(
                    "usage: :alarm-create NAME KIND THRESHOLD [OP]  (KIND: health|4xx|5xx|latency; OP defaults match the kind; no SNS action wired)".into(),
                );
                return;
            }
        };
        if self.read_only {
            self.error_message = Some("read-only mode — alarm-create disabled".into());
            return;
        }
        let Some((metric_name, default_op, stat)) = alarm_kind_to_metric(kind) else {
            self.error_message = Some(format!(
                "unknown KIND '{kind}'  (valid: health, 4xx, 5xx, latency)"
            ));
            return;
        };
        let Ok(threshold) = threshold_raw.parse::<f64>() else {
            self.error_message = Some(format!("threshold '{threshold_raw}' is not a number"));
            return;
        };
        let op = op_override.unwrap_or(default_op);
        let Some(env) = self.selected_env().cloned() else {
            self.error_message = Some("no env selected".into());
            return;
        };
        let env_name = env.name.clone();
        let alarm_name = name.to_string();
        let metric_name = metric_name.to_string();
        let op_str = op.to_string();
        let stat_str = stat.to_string();
        let target = format!("{env_name}/{alarm_name}");
        write_audit_line(
            self.context.account_id.as_deref(),
            self.context.profile.as_deref(),
            &self.context.region,
            &format!(
                "stage=dispatched action=AlarmCreate target={target} metric={metric_name} threshold={threshold} op={op_str}"
            ),
        );
        self.push_pending("Create alarm", target.clone());
        self.status_message = Some(format!(
            "creating alarm '{alarm_name}' on {env_name}/{metric_name} {op_str} {threshold}…"
        ));
        let aws = self.aws.clone();
        let tx = self.msg_tx.clone();
        let gen = self.generation;
        let env_for_msg = env_name.clone();
        let alarm_for_msg = alarm_name.clone();
        let account = self.context.account_id.clone();
        let profile = self.context.profile.clone();
        let region = self.context.region.clone();
        tokio::spawn(async move {
            let result = aws
                .put_env_metric_alarm(
                    &alarm_for_msg,
                    &env_for_msg,
                    &metric_name,
                    threshold,
                    &op_str,
                    300,
                    1,
                    &stat_str,
                )
                .await
                .map_err(|e| flatten_err("put_metric_alarm", e));
            let outcome = match &result {
                Ok(()) => format!("stage=completed action=AlarmCreate target={target} ok"),
                Err(e) => format!(
                    "stage=completed action=AlarmCreate target={target} err=\"{}\"",
                    e.replace('"', "'")
                ),
            };
            write_audit_line(account.as_deref(), profile.as_deref(), &region, &outcome);
            let _ = tx.send(AppMsg::AlarmOp {
                gen,
                verb: "create",
                alarm_name: alarm_for_msg,
                env_name: env_for_msg,
                result,
            });
        });
    }

    pub(crate) fn cmd_alarm_delete(&mut self, rest: &[&str]) {
        match rest.first().copied() {
            None => {
                self.error_message = Some("usage: :alarm-delete NAME".into());
            }
            Some(name) => {
                if self.read_only {
                    self.error_message = Some("read-only mode — alarm-delete disabled".into());
                    return;
                }
                let alarm_name = name.to_string();
                let env_name = self
                    .selected_env()
                    .map(|e| e.name.clone())
                    .unwrap_or_else(|| "?".into());
                let target = format!("{env_name}/{alarm_name}");
                write_audit_line(
                    self.context.account_id.as_deref(),
                    self.context.profile.as_deref(),
                    &self.context.region,
                    &format!("stage=dispatched action=AlarmDelete target={target}"),
                );
                self.push_pending("Delete alarm", target.clone());
                self.status_message = Some(format!("deleting alarm '{alarm_name}'…"));
                let aws = self.aws.clone();
                let tx = self.msg_tx.clone();
                let gen = self.generation;
                let alarm_for_msg = alarm_name.clone();
                let env_for_msg = env_name.clone();
                let account = self.context.account_id.clone();
                let profile = self.context.profile.clone();
                let region = self.context.region.clone();
                tokio::spawn(async move {
                    let result = aws
                        .delete_alarms(std::slice::from_ref(&alarm_for_msg))
                        .await
                        .map_err(|e| flatten_err("delete_alarms", e));
                    let outcome = match &result {
                        Ok(()) => {
                            format!("stage=completed action=AlarmDelete target={target} ok")
                        }
                        Err(e) => format!(
                            "stage=completed action=AlarmDelete target={target} err=\"{}\"",
                            e.replace('"', "'")
                        ),
                    };
                    write_audit_line(account.as_deref(), profile.as_deref(), &region, &outcome);
                    let _ = tx.send(AppMsg::AlarmOp {
                        gen,
                        verb: "delete",
                        alarm_name: alarm_for_msg,
                        env_name: env_for_msg,
                        result,
                    });
                });
            }
        }
    }
}
