use super::{ArgMessage, arg_failure, op_failure};
use crate::cli::ReviewDecisionArg;
use crate::commands::output::emit;
use crate::contracts::{confirm, reject, resolve_prefix, use_candidate_once};
use crate::render::{RenderFormat, TerminalEvent};
use saya_store::SqliteStateStore;
use saya_types::{ClaimStatus, ProfileIdentity};
const MIN_PREFIX_LEN: usize = 2;
pub(super) async fn decide(
store: &SqliteStateStore,
format: RenderFormat,
prefix: &str,
decision: ReviewDecisionArg,
profile_name: &str,
identity: &ProfileIdentity,
) -> Result<i32, Box<dyn std::error::Error>> {
if prefix.len() < MIN_PREFIX_LEN {
return arg_failure(ArgMessage::AmbiguousPrefix, format);
}
let id = match resolve_prefix(store, identity, prefix).await {
Ok(id) => id,
Err(error) => return prefix_failure(error, format),
};
match decision {
ReviewDecisionArg::Confirm => {
let claim = match confirm(store, &id).await {
Ok(claim) => claim,
Err(error) => return op_failure(error, format),
};
emit(
TerminalEvent::ContractChanged {
claim_id: claim.id.as_str().to_string(),
action: "confirmed".into(),
status: "confirmed".into(),
},
format,
);
Ok(0)
}
ReviewDecisionArg::Reject => {
let claim = match reject(store, &id).await {
Ok(claim) => claim,
Err(error) => return op_failure(error, format),
};
let (action, status) = match claim.status {
ClaimStatus::Rejected => ("rejected", "rejected"),
other => ("reviewed", other.as_str()),
};
emit(
TerminalEvent::ContractChanged {
claim_id: claim.id.as_str().to_string(),
action: action.into(),
status: status.into(),
},
format,
);
Ok(0)
}
ReviewDecisionArg::UseOnce => {
if let Err(error) = use_candidate_once(store, &id).await {
return op_failure(error, format);
}
emit(
TerminalEvent::Result {
message: format!(
"{id} is a live candidate; use-once does not confirm it (nothing written, profile: {profile_name})"
),
},
format,
);
Ok(0)
}
}
}
fn prefix_failure(
error: crate::contracts::ContractOpError,
format: RenderFormat,
) -> Result<i32, Box<dyn std::error::Error>> {
match error {
crate::contracts::ContractOpError::Conflict => {
arg_failure(ArgMessage::AmbiguousPrefix, format)
}
crate::contracts::ContractOpError::NotFound => {
arg_failure(ArgMessage::PrefixNotFound, format)
}
other => op_failure(other, format),
}
}