use super::backend::EpicBackend;
use super::render::{self, DEFERRED_END, DEFERRED_HEADER, DEFERRED_START};
#[derive(Debug, Clone)]
pub(crate) struct DeferOptions {
pub(crate) item: String,
pub(crate) why: String,
pub(crate) destination: String,
}
#[derive(Debug, Clone)]
pub(crate) struct DeferReport {
pub(crate) tracker: u64,
pub(crate) row: String,
pub(crate) unchanged: bool,
}
pub(crate) fn defer<B: EpicBackend>(
backend: &B,
tracker: u64,
opts: &DeferOptions,
) -> anyhow::Result<DeferReport> {
for (flag, value) in [
("--item", &opts.item),
("--why", &opts.why),
("--where", &opts.destination),
] {
if value.trim().is_empty() {
anyhow::bail!("`{flag}` is blank — a deferred row needs all three cells");
}
}
let row = format!(
"| {} | {} | {} |",
render::cell(opts.item.trim()),
render::cell(opts.why.trim()),
render::cell(opts.destination.trim())
);
let body = backend.body(tracker)?;
let current = render::block_content(&body, DEFERRED_START, DEFERRED_END)
.map_err(|e| anyhow::anyhow!("#{tracker}: {e}"))?;
if current.lines().any(|l| l.trim() == row) {
return Ok(DeferReport {
tracker,
row,
unchanged: true,
});
}
let content = if current.trim().is_empty() {
format!("{DEFERRED_HEADER}\n{row}")
} else {
format!("{current}\n{row}")
};
let next = render::replace_block(&body, DEFERRED_START, DEFERRED_END, &content)
.map_err(|e| anyhow::anyhow!("#{tracker}: {e}"))?;
backend.set_body(tracker, &next)?;
Ok(DeferReport {
tracker,
row,
unchanged: false,
})
}