use crate::app::App;
use crate::input::Action;
use super::handle_shared_normal_action;
pub fn handle_sparring_panel_action(app: &mut App, action: Action) {
use crate::ui::sparring_panel::build_spec_rows;
let rows = build_spec_rows(app);
let total = rows.len();
match action {
Action::CursorDown(n) => {
if total > 0 {
let max = total - 1;
app.sparring_cursor = (app.sparring_cursor + n).min(max);
}
}
Action::CursorUp(n) => {
app.sparring_cursor = app.sparring_cursor.saturating_sub(n);
}
Action::GoToTop => {
app.sparring_cursor = 0;
}
Action::GoToBottom => {
if total > 0 {
app.sparring_cursor = total - 1;
}
}
Action::SparringAccept => {
let Some(row) = rows.get(app.sparring_cursor) else {
return;
};
if mark_spec_resolved(app, &row.spec_id) {
app.dirty = true;
app.set_message(format!("Spec accepted (resolved): {}", row.preview));
app.refresh_spec_statuses();
let new_total = app.spec_statuses.len();
if new_total == 0 {
app.sparring_cursor = 0;
} else if app.sparring_cursor >= new_total {
app.sparring_cursor = new_total - 1;
}
}
}
Action::PendingDCommand => {
let Some(row) = rows.get(app.sparring_cursor) else {
return;
};
if delete_spec_comment(app, &row.spec_id) {
app.dirty = true;
app.set_message(format!("Spec dropped: {}", row.preview));
app.refresh_spec_statuses();
let new_total = app.spec_statuses.len();
if new_total == 0 {
app.sparring_cursor = 0;
} else if app.sparring_cursor >= new_total {
app.sparring_cursor = new_total - 1;
}
}
}
Action::ToggleReviewed => {
let Some(row) = rows.get(app.sparring_cursor) else {
return;
};
app.set_message(format!(
"Reshape requested for spec {} — ask your agent to regenerate",
&row.spec_id[..8.min(row.spec_id.len())]
));
}
_ => handle_shared_normal_action(app, action),
}
}
fn mark_spec_resolved(app: &mut App, spec_id: &str) -> bool {
use travelagent_core::model::CommentType;
let session = app.engine.session_mut();
let mut updated = false;
let mut mark = |c: &mut travelagent_core::model::Comment| {
if matches!(c.comment_type, CommentType::Spec) && c.id == spec_id && !c.resolved {
c.resolved = true;
updated = true;
}
};
for c in session.review_comments.iter_mut() {
mark(c);
}
for fr in session.files.values_mut() {
for c in fr.file_comments.iter_mut() {
mark(c);
}
for cs in fr.line_comments.values_mut() {
for c in cs.iter_mut() {
mark(c);
}
}
for c in fr.orphaned_comments.iter_mut() {
mark(c);
}
}
updated
}
fn delete_spec_comment(app: &mut App, spec_id: &str) -> bool {
use travelagent_core::model::CommentType;
let session = app.engine.session_mut();
let match_spec = |c: &travelagent_core::model::Comment| {
matches!(c.comment_type, CommentType::Spec) && c.id == spec_id
};
let before = session.review_comments.len();
session.review_comments.retain(|c| !match_spec(c));
if session.review_comments.len() < before {
return true;
}
for fr in session.files.values_mut() {
let before = fr.file_comments.len();
fr.file_comments.retain(|c| !match_spec(c));
if fr.file_comments.len() < before {
return true;
}
for cs in fr.line_comments.values_mut() {
let before = cs.len();
cs.retain(|c| !match_spec(c));
if cs.len() < before {
return true;
}
}
let before = fr.orphaned_comments.len();
fr.orphaned_comments.retain(|c| !match_spec(c));
if fr.orphaned_comments.len() < before {
return true;
}
}
false
}