1use crate::core_loop::{CaseStatus, cases, time};
3use crate::shell::cli::workspace_path;
4use crate::store::Store;
5use anyhow::{Result, anyhow};
6use std::path::Path;
7
8pub fn cmd_cases_mine(workspace: Option<&Path>, since: Option<&str>, json: bool) -> Result<()> {
9 let store = open(workspace)?;
10 let rows = cases::mine(&store, time::parse_window(since, 7)?, time::now_ms())?;
11 output(&rows, json)
12}
13
14pub fn cmd_cases_create(
15 workspace: Option<&Path>,
16 session_id: &str,
17 reason: &str,
18 label: Option<String>,
19 json: bool,
20) -> Result<()> {
21 let store = open(workspace)?;
22 let s = store
23 .get_session(session_id)?
24 .ok_or_else(|| anyhow!("session not found"))?;
25 let key = format!("manual:{session_id}:{reason}");
26 let row = cases::create_case(&store, &s, &key, reason, label, time::now_ms())?;
27 output(&[row], json)
28}
29
30pub fn cmd_cases_list(workspace: Option<&Path>, status: Option<String>, json: bool) -> Result<()> {
31 output(
32 &cases::list(&open(workspace)?, parse_status(status.as_deref()))?,
33 json,
34 )
35}
36
37pub fn cmd_cases_show(workspace: Option<&Path>, id: &str, json: bool) -> Result<()> {
38 let store = open(workspace)?;
39 let row = cases::get(&store, id)?;
40 if json {
41 println!("{}", serde_json::to_string_pretty(&row)?);
42 } else {
43 println!(
44 "{} session={} reason={} status={}",
45 row.id,
46 row.session_id,
47 row.reason,
48 row.status.as_str()
49 );
50 }
51 Ok(())
52}
53
54pub fn cmd_cases_archive(workspace: Option<&Path>, id: &str) -> Result<()> {
55 cases::archive(&open(workspace)?, id)?;
56 println!("archived case {id}");
57 Ok(())
58}
59
60fn open(workspace: Option<&Path>) -> Result<Store> {
61 let ws = workspace_path(workspace)?;
62 Store::open(&crate::core::workspace::db_path(&ws)?)
63}
64
65fn output(rows: &[crate::core_loop::CaseRecord], json: bool) -> Result<()> {
66 if json {
67 println!("{}", serde_json::to_string_pretty(rows)?);
68 } else {
69 rows.iter().for_each(|r| {
70 println!(
71 "{} session={} reason={} status={}",
72 r.id,
73 r.session_id,
74 r.reason,
75 r.status.as_str()
76 )
77 });
78 }
79 Ok(())
80}
81
82fn parse_status(raw: Option<&str>) -> Option<CaseStatus> {
83 raw.map(|s| {
84 if s == "archived" {
85 CaseStatus::Archived
86 } else {
87 CaseStatus::Open
88 }
89 })
90}