use ratatui::Frame;
use ratatui::layout::Rect;
use ratatui::style::{Color, Modifier, Style};
use ratatui::text::{Line, Span};
use ratatui::widgets::{Block, Borders, Clear, Paragraph, Wrap};
use crate::tui::app::App;
use crate::utils::plan_files::{self, PlanModeState};
pub(super) fn render_plan_overlay(f: &mut Frame, app: &App, area: Rect) {
f.render_widget(Clear, area);
if app.current_session.is_none() {
let p = Paragraph::new("No active session.")
.block(Block::default().borders(Borders::ALL).title(" Plan "));
f.render_widget(p, area);
return;
}
let md_path = app.plan_file_path.as_ref().map(|p| p.with_extension("md"));
let md_exists = md_path.as_ref().is_some_and(|p| p.exists());
let state = plan_files::plan_mode_state_of(app.plan_document.as_ref(), md_exists);
let (badge, badge_style) = match state {
PlanModeState::NoPlan => ("no plan", Style::default().fg(Color::DarkGray)),
PlanModeState::PreInitEditing => (
"Editing · pre-init",
Style::default()
.fg(Color::Yellow)
.add_modifier(Modifier::BOLD),
),
PlanModeState::PostInitEditing => (
"Editing",
Style::default()
.fg(Color::Yellow)
.add_modifier(Modifier::BOLD),
),
PlanModeState::Active => (
"Active",
Style::default()
.fg(Color::Green)
.add_modifier(Modifier::BOLD),
),
};
let body: String = match state {
PlanModeState::NoPlan => "No live plan for this session.\n\nStart one with /plan \
(design track) or ask for a checklist."
.to_string(),
PlanModeState::PreInitEditing => "Plan mode is on, but `plan init` has not created \
the design document yet.\n\nDescribe what you want \
planned; the agent explores, then drafts the \
SESSION PLAN for your approval. Leave Plan mode \
with /discard."
.to_string(),
PlanModeState::PostInitEditing => md_path
.as_ref()
.and_then(|p| std::fs::read_to_string(p).ok())
.unwrap_or_else(|| "(the session plan .md is unreadable)".to_string()),
PlanModeState::Active => app
.plan_document
.as_ref()
.map(crate::utils::plan_mode::format_active_checklist)
.unwrap_or_else(|| "Plan JSON is unreadable.".to_string()),
};
let title = Line::from(vec![
Span::raw(" 📋 Plan · "),
Span::styled(badge, badge_style),
Span::raw(" "),
]);
let footer = match state {
PlanModeState::PostInitEditing => {
" a approve · d discard · ↑/↓ scroll · Esc close (validator runs on approve) "
}
PlanModeState::Active => " d discard · ↑/↓ scroll · Esc close ",
PlanModeState::PreInitEditing => " d discard (leave Plan mode) · Esc close ",
PlanModeState::NoPlan => " Esc close ",
};
let block = Block::default()
.borders(Borders::ALL)
.title(title)
.title_bottom(Line::from(Span::styled(
footer,
Style::default().fg(Color::DarkGray),
)));
let paragraph = Paragraph::new(body)
.block(block)
.wrap(Wrap { trim: false })
.scroll((app.plan_overlay_scroll as u16, 0));
f.render_widget(paragraph, area);
}