use crate::cli::{SprintAction, SprintUpdateArgs};
use crate::context::CliContext;
use crate::output;
use kanban_core::{parse_datetime_input, resolve_page_params, PaginatedList};
use kanban_domain::{FieldUpdate, KanbanOperations, SprintUpdate};
pub async fn handle(ctx: &mut CliContext, action: SprintAction) -> anyhow::Result<()> {
match action {
SprintAction::Create {
board,
prefix,
name,
} => {
let board_uuid = match ctx.resolve_board_id(&board) {
Ok(u) => u,
Err(e) => return output::output_error(&e.to_string()),
};
let sprint = ctx.create_sprint(board_uuid, prefix, name)?;
ctx.save().await?;
output::output_success(&sprint);
}
SprintAction::List {
board,
page,
page_size,
} => {
let board_uuid = match ctx.resolve_board_id(&board) {
Ok(u) => u,
Err(e) => return output::output_error(&e.to_string()),
};
let sprints = ctx.list_sprints(board_uuid)?;
let (page, page_size) = resolve_page_params(page, page_size)?;
output::output_success(PaginatedList::paginate(sprints, page, page_size)?);
}
SprintAction::Get { sprint } => {
let uuid = match ctx.resolve_sprint_id_global(&sprint) {
Ok(u) => u,
Err(e) => return output::output_error(&e.to_string()),
};
match ctx.get_sprint(uuid)? {
Some(s) => output::output_success(&s),
None => return output::output_error(&format!("Sprint not found: {}", sprint)),
}
}
SprintAction::Update(args) => {
let sprint = match handle_update(ctx, args).await {
Ok(s) => s,
Err(e) => return output::output_error(&e.to_string()),
};
output::output_success(&sprint);
}
SprintAction::Activate {
sprint,
duration_days,
} => {
let uuid = match ctx.resolve_sprint_id_global(&sprint) {
Ok(u) => u,
Err(e) => return output::output_error(&e.to_string()),
};
let activated = ctx.activate_sprint(uuid, duration_days)?;
ctx.save().await?;
output::output_success(&activated);
}
SprintAction::Complete { sprint } => {
let uuid = match ctx.resolve_sprint_id_global(&sprint) {
Ok(u) => u,
Err(e) => return output::output_error(&e.to_string()),
};
let completed = ctx.complete_sprint(uuid)?;
ctx.save().await?;
output::output_success(&completed);
}
SprintAction::Cancel { sprint } => {
let uuid = match ctx.resolve_sprint_id_global(&sprint) {
Ok(u) => u,
Err(e) => return output::output_error(&e.to_string()),
};
let cancelled = ctx.cancel_sprint(uuid)?;
ctx.save().await?;
output::output_success(&cancelled);
}
SprintAction::Delete { sprint } => {
let uuid = match ctx.resolve_sprint_id_global(&sprint) {
Ok(u) => u,
Err(e) => return output::output_error(&e.to_string()),
};
ctx.delete_sprint(uuid)?;
ctx.save().await?;
output::output_success(serde_json::json!({"deleted": uuid.to_string()}));
}
SprintAction::CarryOver { from, to } => {
let from_uuid = match ctx.resolve_sprint_id_global(&from) {
Ok(u) => u,
Err(e) => return output::output_error(&e.to_string()),
};
let from_sprint = ctx
.get_sprint(from_uuid)?
.ok_or_else(|| anyhow::anyhow!("Source sprint not found: {}", from_uuid))?;
let to_uuid = match ctx.resolve_sprint_id(&to, from_sprint.board_id) {
Ok(u) => u,
Err(e) => return output::output_error(&e.to_string()),
};
let count = ctx.carry_over_sprint_cards(from_uuid, to_uuid)?;
ctx.save().await?;
output::output_success(serde_json::json!({ "carried_over": count }));
}
}
Ok(())
}
async fn handle_update(
ctx: &mut CliContext,
args: SprintUpdateArgs,
) -> anyhow::Result<kanban_domain::Sprint> {
let uuid = ctx
.resolve_sprint_id_global(&args.sprint)
.map_err(anyhow::Error::from)?;
let start_date = if args.clear_start_date {
FieldUpdate::Clear
} else {
match args.start_date {
Some(d) => FieldUpdate::Set(parse_datetime_input(&d).map_err(anyhow::Error::msg)?),
None => FieldUpdate::NoChange,
}
};
let end_date = if args.clear_end_date {
FieldUpdate::Clear
} else {
match args.end_date {
Some(d) => FieldUpdate::Set(parse_datetime_input(&d).map_err(anyhow::Error::msg)?),
None => FieldUpdate::NoChange,
}
};
let updates = SprintUpdate {
name: args.name,
name_index: FieldUpdate::NoChange,
prefix: args
.prefix
.map(FieldUpdate::Set)
.unwrap_or(FieldUpdate::NoChange),
card_prefix: args
.card_prefix
.map(FieldUpdate::Set)
.unwrap_or(FieldUpdate::NoChange),
status: None,
start_date,
end_date,
};
let sprint = ctx.update_sprint(uuid, updates)?;
ctx.save().await?;
Ok(sprint)
}