use super::TelegramState;
use super::flow_chrome::{PlanKb, load_plan_sections};
use super::handler::escape_html;
use super::send::message_in_thread;
use std::sync::Arc;
use teloxide::prelude::*;
use teloxide::types::{ParseMode, ThreadId};
use uuid::Uuid;
pub(crate) fn render_plan_card_html(
title: Option<&str>,
checklist: Option<&[String]>,
) -> Option<String> {
let mut out = String::new();
if let Some(t) = title.map(str::trim).filter(|t| !t.is_empty()) {
out.push_str(&format!("<b>📋 {}</b>", escape_html(t)));
}
if let Some(rows) = checklist {
for row in rows {
if !out.is_empty() {
out.push('\n');
}
out.push_str(&escape_html(row));
}
}
(!out.is_empty()).then_some(out)
}
pub(crate) async fn refresh_plan_card(
bot: &Bot,
chat: ChatId,
thread_id: Option<ThreadId>,
state: &Arc<TelegramState>,
session_id: Uuid,
plan_kb: PlanKb,
) {
let (title, checklist) = load_plan_sections(session_id).await;
let Some(html) = render_plan_card_html(title.as_deref(), checklist.as_deref()) else {
remove_plan_card(bot, chat, state, session_id).await;
return;
};
let kb = plan_kb.keyboard();
let signature = format!("{html}\u{1}{plan_kb:?}");
if let Some((mid, last_sig)) = state.plan_card(session_id).await {
if last_sig == signature {
return; }
let mut req = bot
.edit_message_text(chat, mid, html.clone())
.parse_mode(ParseMode::Html);
if let Some(ref k) = kb {
req = req.reply_markup(k.clone());
}
match req.await {
Ok(_) => {
state.set_plan_card(session_id, mid, signature).await;
return;
}
Err(e) => {
let es = e.to_string();
if es.contains("message is not modified") {
state.set_plan_card(session_id, mid, signature).await;
return;
}
tracing::debug!("Telegram plan card edit failed ({mid:?}): {es} — recreating");
state.take_plan_card(session_id).await;
}
}
}
let mut req = message_in_thread(bot, chat, thread_id, html).parse_mode(ParseMode::Html);
if let Some(ref k) = kb {
req = req.reply_markup(k.clone());
}
match req.await {
Ok(m) => state.set_plan_card(session_id, m.id, signature).await,
Err(e) => tracing::warn!("Telegram plan card create failed: {e}"),
}
}
pub(crate) async fn remove_plan_card(
bot: &Bot,
chat: ChatId,
state: &Arc<TelegramState>,
session_id: Uuid,
) {
if let Some(mid) = state.take_plan_card(session_id).await
&& let Err(e) = bot.delete_message(chat, mid).await
{
tracing::debug!("Telegram plan card delete failed ({mid:?}): {e}");
}
}