diff --git a/src/cli/commands/count.rs b/src/cli/commands/count.rs index 42020df..751d91e 100644 --- a/src/cli/commands/count.rs +++ b/src/cli/commands/count.rs @@ -7,6 +7,7 @@ use serde::Serialize; use crate::Config; use crate::core::db::create_connection; use crate::core::error::Result; +use crate::core::events_db::{self, EventCounts}; use crate::core::paths::get_db_path; /// Result of count query. @@ -237,6 +238,109 @@ struct CountJsonBreakdown { locked: Option, } +/// Run the event count query. +pub fn run_count_events(config: &Config) -> Result { + let db_path = get_db_path(config.storage.db_path.as_deref()); + let conn = create_connection(&db_path)?; + events_db::count_events(&conn) +} + +/// JSON output structure for event counts. +#[derive(Serialize)] +struct EventCountJsonOutput { + ok: bool, + data: EventCountJsonData, +} + +#[derive(Serialize)] +struct EventCountJsonData { + state_events: EventTypeCounts, + label_events: EventTypeCounts, + milestone_events: EventTypeCounts, + total: usize, +} + +#[derive(Serialize)] +struct EventTypeCounts { + issue: usize, + merge_request: usize, + total: usize, +} + +/// Print event counts as JSON (robot mode). +pub fn print_event_count_json(counts: &EventCounts) { + let output = EventCountJsonOutput { + ok: true, + data: EventCountJsonData { + state_events: EventTypeCounts { + issue: counts.state_issue, + merge_request: counts.state_mr, + total: counts.state_issue + counts.state_mr, + }, + label_events: EventTypeCounts { + issue: counts.label_issue, + merge_request: counts.label_mr, + total: counts.label_issue + counts.label_mr, + }, + milestone_events: EventTypeCounts { + issue: counts.milestone_issue, + merge_request: counts.milestone_mr, + total: counts.milestone_issue + counts.milestone_mr, + }, + total: counts.total(), + }, + }; + + println!("{}", serde_json::to_string(&output).unwrap()); +} + +/// Print event counts (human-readable). +pub fn print_event_count(counts: &EventCounts) { + println!( + "{:<20} {:>8} {:>8} {:>8}", + style("Event Type").cyan().bold(), + style("Issues").bold(), + style("MRs").bold(), + style("Total").bold() + ); + + let state_total = counts.state_issue + counts.state_mr; + let label_total = counts.label_issue + counts.label_mr; + let milestone_total = counts.milestone_issue + counts.milestone_mr; + + println!( + "{:<20} {:>8} {:>8} {:>8}", + "State events", + format_number(counts.state_issue as i64), + format_number(counts.state_mr as i64), + format_number(state_total as i64) + ); + println!( + "{:<20} {:>8} {:>8} {:>8}", + "Label events", + format_number(counts.label_issue as i64), + format_number(counts.label_mr as i64), + format_number(label_total as i64) + ); + println!( + "{:<20} {:>8} {:>8} {:>8}", + "Milestone events", + format_number(counts.milestone_issue as i64), + format_number(counts.milestone_mr as i64), + format_number(milestone_total as i64) + ); + + let total_issues = counts.state_issue + counts.label_issue + counts.milestone_issue; + let total_mrs = counts.state_mr + counts.label_mr + counts.milestone_mr; + println!( + "{:<20} {:>8} {:>8} {:>8}", + style("Total").bold(), + format_number(total_issues as i64), + format_number(total_mrs as i64), + style(format_number(counts.total() as i64)).bold() + ); +} + /// Print count result as JSON (robot mode). pub fn print_count_json(result: &CountResult) { let breakdown = result.state_breakdown.as_ref().map(|b| CountJsonBreakdown { diff --git a/src/cli/commands/mod.rs b/src/cli/commands/mod.rs index cede53e..98ba1a4 100644 --- a/src/cli/commands/mod.rs +++ b/src/cli/commands/mod.rs @@ -15,7 +15,10 @@ pub mod sync; pub mod sync_status; pub use auth_test::run_auth_test; -pub use count::{print_count, print_count_json, run_count}; +pub use count::{ + print_count, print_count_json, print_event_count, print_event_count_json, run_count, + run_count_events, +}; pub use doctor::{print_doctor_results, run_doctor}; pub use embed::{print_embed, print_embed_json, run_embed}; pub use generate_docs::{print_generate_docs, print_generate_docs_json, run_generate_docs};