Skip to main content

kasl/libs/messages/
display.rs

1//! Display implementation for kasl application messages.
2//!
3//! Provides the core `Display` trait implementation for the `Message` enum, enabling automatic conversion of structured message data into human-readable text.
4//!
5//! ## Features
6//!
7//! - **Single Source of Truth**: All message text is defined in one location
8//! - **Type Safety**: Compile-time verification of message parameter usage
9//! - **Internationalization Ready**: Structured for future localization support
10//! - **Consistent Formatting**: Uniform message presentation across the application
11//! - **Parameter Interpolation**: Safe string formatting with typed parameters
12//!
13//! ## Usage
14//!
15//! ```rust
16//! use kasl::libs::messages::types::Message;
17//!
18//! let message = Message::TaskCreated;
19//! println!("{}", message);
20//!
21//! let parameterized = Message::MonitorStarted {
22//!     pause_threshold: 60,
23//!     poll_interval: 500,
24//!     activity_threshold: 30,
25//! };
26//! println!("{}", parameterized);
27//! ```
28
29use super::types::Message;
30use std::fmt::{Display, Formatter, Result};
31
32impl Display for Message {
33    /// Converts a `Message` enum variant into human-readable text.
34    ///
35    /// This method implements the core message-to-text conversion logic for
36    /// the entire kasl application. It provides consistent, professional
37    /// text formatting for all user-facing messages while maintaining
38    /// type safety and parameter interpolation.
39    ///
40    /// ## Implementation Strategy
41    ///
42    /// The method uses a comprehensive match statement to handle each message
43    /// variant individually, ensuring that:
44    /// - All message types are explicitly handled
45    /// - Parameter interpolation is type-safe
46    /// - Text formatting is consistent across message categories
47    /// - New message types require explicit formatting decisions
48    ///
49    /// ## Text Quality Standards
50    ///
51    /// All generated text adheres to these quality standards:
52    /// - **Clarity**: Messages are easily understood by users
53    /// - **Specificity**: Include relevant details and context
54    /// - **Actionability**: Provide guidance for next steps when appropriate
55    /// - **Professionalism**: Suitable for business and personal environments
56    /// - **Consistency**: Uniform tone and style across all messages
57    ///
58    /// ## Parameter Handling
59    ///
60    /// Messages with parameters use safe string interpolation:
61    /// - String parameters are inserted directly
62    /// - Numeric parameters are formatted appropriately
63    /// - Collections are joined with appropriate separators
64    /// - Optional values are handled with meaningful defaults
65    ///
66    /// ## Error Message Philosophy
67    ///
68    /// Error messages are designed to be helpful rather than technical:
69    /// - Focus on user-understandable problems
70    /// - Suggest concrete resolution steps
71    /// - Avoid intimidating technical jargon
72    /// - Provide sufficient context for troubleshooting
73    ///
74    /// # Arguments
75    ///
76    /// * `f` - The formatter for writing the text output
77    ///
78    /// # Returns
79    ///
80    /// Returns `Ok(())` if the message was successfully formatted,
81    /// or an error if the formatting operation fails.
82    ///
83    /// # Error Scenarios
84    ///
85    /// - **Formatter Errors**: Underlying write operations fail
86    /// - **Memory Allocation**: Insufficient memory for string operations
87    /// - **Parameter Formatting**: Invalid parameter values (rare)
88    ///
89    /// # Examples
90    ///
91    /// ```rust
92    /// use kasl::libs::messages::Message;
93    ///
94    /// // Automatic formatting through Display trait
95    /// let message = Message::TaskCreated;
96    /// println!("{}", message); // "Task created successfully"
97    ///
98    /// // With parameters
99    /// let date_message = Message::WorkdayStarting("2025-01-15".to_string());
100    /// println!("{}", date_message); // "Starting workday for 2025-01-15"
101    /// ```
102    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
103        let text = match self {
104            // === AUTOSTART MESSAGES ===
105            Message::AutostartEnabled => "Autostart has been enabled. Kasl will start automatically on system boot.".to_string(),
106            Message::AutostartEnabledUser => "Autostart has been enabled for current user. Kasl will start when you log in.".to_string(),
107            Message::AutostartDisabled => "Autostart has been disabled.".to_string(),
108            Message::AutostartAlreadyDisabled => "Autostart was already disabled.".to_string(),
109            Message::AutostartEnableFailed(error) => format!("Failed to enable autostart: {}", error),
110            Message::AutostartDisableFailed(error) => format!("Failed to disable autostart: {}", error),
111            Message::AutostartStatus(status) => format!("Autostart is currently: {}", status),
112            Message::AutostartNotImplemented => "Autostart is not yet implemented for this operating system.".to_string(),
113            Message::AutostartRequiresAdmin => "Administrator privileges required for system-level autostart. Trying user-level alternative...".to_string(),
114            Message::AutostartCheckingAlternative => "Checking alternative autostart method...".to_string(),
115
116            // === TASK MESSAGES ===
117            Message::TaskCreated => "Task created successfully".to_string(),
118            Message::TaskUpdated => "Task updated successfully".to_string(),
119            Message::TaskDeleted => "Task deleted successfully".to_string(),
120            Message::TaskNotFound => "Task not found".to_string(),
121            Message::TaskCreateFailed => "Failed to create task".to_string(),
122            Message::TaskUpdateFailed => "Failed to update task".to_string(),
123            Message::TaskDeleteFailed => "Failed to delete task".to_string(),
124            Message::TasksDeletedCount(count) => format!("Deleted {} task(s) successfully.", count),
125            Message::TasksNotFoundForDate(date) => format!("Tasks not found for {}, report not sent.", date),
126            Message::TasksNotFoundSad => "No tasks found.".to_string(),
127            Message::TasksHeader => "Tasks:".to_string(),
128            Message::TasksIncompleteHeader => "Incomplete tasks".to_string(),
129            Message::TasksGitlabHeader => "Gitlab commits".to_string(),
130            Message::TasksJiraHeader => "Jira issues".to_string(),
131            Message::TasksDiscoverySummary {
132                incomplete,
133                jira,
134                gitlab,
135            } => {
136                let mut parts = Vec::new();
137                if *incomplete > 0 {
138                    parts.push(format!("{} incomplete", incomplete));
139                }
140                if *jira > 0 {
141                    parts.push(format!("{} jira", jira));
142                }
143                if *gitlab > 0 {
144                    parts.push(format!("{} gitlab", gitlab));
145                }
146                format!("Found: {}", parts.join(", "))
147            }
148            Message::TasksDiscoverySeparator => "──────── other ────────".to_string(),
149            Message::TasksDiscoverySearchingIncomplete => "Looking for incomplete tasks...".to_string(),
150            Message::TasksDiscoveryFetchingExternal => "Fetching GitLab commits and Jira issues...".to_string(),
151            Message::NoTaskIdsProvided => "No task IDs provided for deletion.".to_string(),
152            Message::TasksNotFoundForIds(ids) => format!("No tasks found with IDs: {:?}", ids),
153            Message::TasksToBeDeleted => "The following tasks will be deleted:".to_string(),
154            Message::ConfirmDeleteTask => "Are you sure you want to delete this task?".to_string(),
155            Message::ConfirmDeleteTasks(count) => format!("Are you sure you want to delete {} tasks?", count),
156            Message::ConfirmDeleteAllTodayTasks(count) => format!("Are you sure you want to delete ALL {} tasks for today?", count),
157            Message::ConfirmDeleteAllTodayTasksFinal => "This action cannot be undone. Are you REALLY sure?".to_string(),
158            Message::NoTasksForToday => "No tasks found for today.".to_string(),
159            Message::TaskNotFoundWithId(id) => format!("Task with ID {} not found.", id),
160            Message::CurrentTaskState => "Current task:".to_string(),
161            Message::TaskEditPreview => "Task after changes:".to_string(),
162            Message::ConfirmTaskUpdate => "Save changes?".to_string(),
163            Message::NoChangesDetected => "No changes detected.".to_string(),
164            Message::NoTasksSelected => "No tasks selected for editing.".to_string(),
165            Message::SelectTasksToEdit => "Select tasks to edit (space to select, enter to confirm)".to_string(),
166            Message::EditingTask(name) => format!("Editing task: {}", name),
167            Message::TaskUpdatedWithName(name) => format!("Task '{}' updated successfully.", name),
168            Message::TaskSkippedNoChanges(name) => format!("Task '{}' - no changes, skipped.", name),
169            Message::TaskEditingCompleted => "Task editing completed.".to_string(),
170            Message::PromptTaskNameEdit => "Task name".to_string(),
171            Message::PromptTaskCommentEdit => "Comment (optional)".to_string(),
172            Message::PromptTaskCompletenessEdit => "Completeness (0-100)".to_string(),
173            Message::TaskCompletenessRange => "Completeness must be between 0 and 100".to_string(),
174
175            // === WORKDAY MESSAGES ===
176            Message::WorkdayEnded => "Workday ended for today.".to_string(),
177            Message::WorkdayNotFound => "No workday record found".to_string(),
178            Message::WorkdayNotFoundForDate(date) => format!("No workday record found for {}", date),
179            Message::WorkdayCreateFailed => "Failed to create workday".to_string(),
180            Message::WorkdayStarting(date) => format!("Starting workday for {}", date),
181            Message::WorkdayCouldNotFindAfterFinalizing(date) => {
182                format!("Could not find workday for {} after finalizing.", date)
183            }
184
185            // === CONFIGURATION MESSAGES ===
186            Message::ConfigSaved => "Configuration saved successfully".to_string(),
187            Message::ConfigDeleted => "Configuration deleted successfully".to_string(),
188            Message::ConfigLoaded => "Configuration loaded successfully".to_string(),
189            Message::ConfigFileNotFound => "Configuration file not found".to_string(),
190            Message::ConfigParseError => "Failed to parse configuration".to_string(),
191            Message::ConfigSaveError => "Failed to save configuration".to_string(),
192            Message::ConfigModuleGitLab => "GitLab settings".to_string(),
193            Message::ConfigModuleJira => "Jira settings".to_string(),
194            Message::ConfigModuleSiServer => "SiServer settings".to_string(),
195            Message::ConfigModuleMonitor => "Monitor settings".to_string(),
196            Message::ConfigModuleServer => "Server settings".to_string(),
197            Message::ConfigModuleProductivity => "Productivity settings".to_string(),
198            Message::ConfigModuleTaskDiscovery => "Task discovery settings".to_string(),
199            Message::TaskDiscoveryIgnoreListHeader => "Current ignore list:".to_string(),
200            Message::TaskDiscoveryIgnoreListEmpty => "Ignore list is empty.".to_string(),
201            Message::TaskDiscoveryIgnoreNameAdded(name) => format!("Added '{}' to ignore list.", name),
202            Message::TaskDiscoveryIgnoreNameExists(name) => format!("'{}' is already in the ignore list.", name),
203            Message::TaskDiscoveryIgnoreNamesAdded(count) => {
204                format!("Added {} name(s) to the discovery ignore list.", count)
205            }
206
207            // === REPORT MESSAGES ===
208            Message::DailyReportSent(date) => {
209                format!(
210                    "Your report dated {} has been successfully submitted\nWait for a message to your email address",
211                    date
212                )
213            }
214            Message::MonthlyReportSent(date) => {
215                format!(
216                    "Your monthly report dated {} has been successfully submitted\nWait for a message to your email address",
217                    date
218                )
219            }
220            Message::MonthlyReportTriggered => "It's the last working day of the month. Submitting the monthly report as well...".to_string(),
221            Message::ReportSendFailed(status) => format!("Failed to send report. Status: {}", status),
222            Message::MonthlyReportSendFailed(status) => format!("Failed to send monthly report. Status: {}", status),
223            Message::ReportHeader(date) => format!("Report for {}", date),
224            Message::WorkingHoursForMonth(month_year) => format!("Working hours for {}", month_year),
225
226            // === EXPORT MESSAGES ===
227            Message::ExportingData(data, format) => format!("Exporting {} in {} format...", data, format),
228            Message::ExportCompleted(path) => format!("Export completed successfully: {}", path),
229            Message::ExportingAllData => "Exporting all data...".to_string(),
230            Message::ExportFailed(error) => format!("Export failed: {}", error),
231
232            // === TEMPLATE MESSAGES ===
233            Message::TemplateCreated(name) => format!("Template '{}' created successfully.", name),
234            Message::TemplateUpdated(name) => format!("Template '{}' updated successfully.", name),
235            Message::TemplateDeleted(name) => format!("Template '{}' deleted successfully.", name),
236            Message::TemplateNotFound(name) => format!("Template '{}' not found.", name),
237            Message::TemplateAlreadyExists(name) => format!("Template '{}' already exists.", name),
238            Message::TemplateCreateFailed => "Failed to create template.".to_string(),
239            Message::NoTemplatesFound => "No templates found.".to_string(),
240            Message::TemplateListHeader => "Task Templates:".to_string(),
241            Message::SelectTemplateToEdit => "Select template to edit".to_string(),
242            Message::SelectTemplateToDelete => "Select template to delete".to_string(),
243            Message::ConfirmDeleteTemplate(name) => format!("Delete template '{}'?", name),
244            Message::EditingTemplate(name) => format!("Editing template: {}", name),
245            Message::NoTemplatesMatchingQuery(query) => format!("No templates matching '{}'", query),
246            Message::TemplateSearchResults(query) => format!("Templates matching '{}':", query),
247            Message::SelectTemplateAction => "What would you like to do?".to_string(),
248            Message::PromptTemplateName => "Template name (unique identifier)".to_string(),
249            Message::PromptTemplateTaskName => "Task name".to_string(),
250            Message::PromptTemplateComment => "Comment (optional)".to_string(),
251            Message::PromptTemplateCompleteness => "Default completeness (0-100)".to_string(),
252            Message::CreatingTaskFromTemplate(name) => format!("Creating task from template '{}'", name),
253            Message::SelectTemplate => "Select a template".to_string(),
254            Message::CreateTemplateFirst => "Create templates with 'kasl template create'".to_string(),
255
256            // === TAG MESSAGES ===
257            Message::TagCreated(name) => format!("Tag '{}' created successfully.", name),
258            Message::TagUpdated(name) => format!("Tag '{}' updated successfully.", name),
259            Message::TagDeleted(name) => format!("Tag '{}' deleted successfully.", name),
260            Message::TagNotFound(name) => format!("Tag '{}' not found.", name),
261            Message::TagAlreadyExists(name) => format!("Tag '{}' already exists.", name),
262            Message::NoTagsFound => "No tags found.".to_string(),
263            Message::TagListHeader => "Tags:".to_string(),
264            Message::EditingTag(name) => format!("Editing tag: {}", name),
265            Message::SelectTagAction => "What would you like to do?".to_string(),
266            Message::SelectTagToEdit => "Select tag to edit".to_string(),
267            Message::SelectTagToDelete => "Select tag to delete".to_string(),
268            Message::ConfirmDeleteTag(name) => format!("Delete tag '{}'?", name),
269            Message::ConfirmDeleteTagWithTasks(name, count) => format!("Tag '{}' is used by {} task(s). Delete anyway?", name, count),
270            Message::PromptTagName => "Tag name".to_string(),
271            Message::PromptTagColor => "Tag color (e.g., blue, green, red)".to_string(),
272            Message::NoTasksWithTag(tag) => format!("No tasks found with tag '{}'.", tag),
273            Message::TasksWithTag(tag) => format!("Tasks with tag '{}':", tag),
274            Message::TagsAddedToTask(tags) => format!("Tags added: {}", tags),
275
276            // === SHORT INTERVALS MESSAGES ===
277            Message::ShortIntervalsDetected(count, duration) => format!("Found {} short work intervals (total: {})", count, duration),
278            Message::NoShortIntervalsFound(min) => format!("No work intervals shorter than {} minutes found.", min),
279            Message::ShortIntervalsToRemove(count) => format!("Found {} short intervals to remove:", count),
280            Message::RemovingPauses(count) => format!("Removing {} pauses to merge intervals...", count),
281            Message::ShortIntervalsCleared(count) => format!("Successfully removed {} pauses and merged intervals.", count),
282            Message::NoRemovablePausesFound => "No pauses found that can be removed to clear short intervals.".to_string(),
283            Message::UpdatedReport => "Updated report:".to_string(),
284            Message::PromptMinWorkInterval => "Minimum work interval (minutes)".to_string(),
285
286            // === TIME ADJUSTMENT MESSAGES ===
287            Message::SelectAdjustmentMode => "Select adjustment mode".to_string(),
288            Message::PromptAdjustmentMinutes => "How many minutes to adjust?".to_string(),
289            Message::PromptPauseStartTime => "When should the pause start? (HH:MM)".to_string(),
290            Message::ConfirmTimeAdjustment => "Apply this time adjustment?".to_string(),
291            Message::TimeAdjustmentApplied => "Time adjustment applied successfully.".to_string(),
292            Message::AdjustmentPreview => "Time adjustment preview:".to_string(),
293            Message::InvalidAdjustmentTooMuchTime => "Cannot adjust that much time - would result in invalid workday.".to_string(),
294            Message::InvalidPauseOutsideWorkday => "Pause must be within workday hours.".to_string(),
295            Message::WorkdayUpdateFailed => "Failed to update workday.".to_string(),
296
297            // === PAUSE MESSAGES ===
298            Message::PausesTitle(date) => format!("Pauses for {}", date),
299
300            // === MONITOR MESSAGES ===
301            Message::MonitorStarted {
302                pause_threshold,
303                poll_interval,
304                activity_threshold,
305            } => {
306                format!(
307                    "Monitor is running with pause threshold {}s, poll interval {}ms, activity threshold {}s",
308                    pause_threshold, poll_interval, activity_threshold
309                )
310            }
311            Message::MonitorStopped => "Monitor stopped".to_string(),
312            Message::MonitorStartFailed => "Failed to start monitor".to_string(),
313            Message::MonitorStopFailed => "Failed to stop monitor".to_string(),
314            Message::MonitorExitedNormally => "Monitor exited normally".to_string(),
315            Message::MonitorShuttingDown => "Shutting down monitor...".to_string(),
316            Message::MonitorError(error) => format!("Monitor error: {}", error),
317            Message::MonitorTaskPanicked(error) => format!("Monitor task panicked: {}", error),
318            Message::PauseStarted => "Pause Start".to_string(),
319            Message::PauseEnded => "Pause End".to_string(),
320
321            // === WATCHER/DAEMON MESSAGES ===
322            Message::WatcherStarted(pid) => format!("Watcher started in the background (PID: {}).", pid),
323            Message::WatcherStopped(pid) => format!("Watcher process (PID: {}) stopped successfully.", pid),
324            Message::WatcherStoppedSuccessfully => "Watcher stopped successfully".to_string(),
325            Message::WatcherNotRunning => "Watcher is not running.".to_string(),
326            Message::WatcherNotRunningPidNotFound => "Watcher does not appear to be running (PID file not found).".to_string(),
327            Message::WatcherStartingForeground => "Starting watcher in foreground... Press Ctrl+C to exit.".to_string(),
328            Message::WatcherStoppingExisting(pid) => format!("Stopping existing watcher (PID: {})...", pid),
329            Message::WatcherFailedToStopExisting(error) => format!("Warning: Failed to stop existing daemon: {}", error),
330            Message::WatcherFailedToStop(pid) => format!("Failed to stop watcher process (PID: {})", pid),
331            Message::WatcherReceivedSigterm => "Received SIGTERM, shutting down gracefully...".to_string(),
332            Message::WatcherReceivedSigint => "Received SIGINT, shutting down gracefully...".to_string(),
333            Message::WatcherReceivedCtrlC => "Received Ctrl+C, shutting down gracefully...".to_string(),
334            Message::WatcherCtrlCListenFailed(error) => format!("Failed to listen for Ctrl+C: {}", error),
335            Message::WatcherSignalHandlingNotSupported => "Warning: Signal handling not supported on this platform".to_string(),
336            Message::DaemonModeNotSupported => "Daemon mode is not supported on this platform.".to_string(),
337            Message::FailedToGetCurrentExecutable => "Failed to get the path of the current executable".to_string(),
338            Message::FailedToCreateSigtermHandler => "Failed to create SIGTERM handler".to_string(),
339            Message::FailedToCreateSigintHandler => "Failed to create SIGINT handler".to_string(),
340
341            // === UPDATE MESSAGES ===
342            Message::UpdateAvailable { app_name, latest } => {
343                format!(
344                    "A new version of {} is available: v{}\nUpgrade now by running: {} update",
345                    app_name, latest, app_name
346                )
347            }
348            Message::UpdateCompleted { app_name, version } => {
349                format!("The {} application has been successfully updated to version {}!", app_name, version)
350            }
351            Message::NoUpdateRequired => "No update required. You are using the latest version!".to_string(),
352            Message::UpdateDownloadUrlNotSet => "Download URL not set".to_string(),
353            Message::WatcherStoppingForUpdate => "Stopping watcher for update...".to_string(),
354            Message::WatcherRestartingAfterUpdate => "Restarting watcher after update...".to_string(),
355            Message::WatcherStoppingForConfig => "Stopping watcher to apply new configuration...".to_string(),
356            Message::WatcherRestartingAfterConfig => "Restarting watcher with updated configuration...".to_string(),
357            Message::WatcherRestarted => "Watcher successfully restarted with new configuration".to_string(),
358            Message::WatcherRestartFailed { error } => format!("Warning: Failed to restart watcher: {}", error),
359            Message::UpdateBinaryNotFoundInArchive => "Binary not found in the release archive.".to_string(),
360
361            // === AUTHENTICATION MESSAGES ===
362            Message::WrongPassword(count) => format!("You entered the wrong password {} times!", count),
363            Message::InvalidCredentials => "Invalid credentials".to_string(),
364            Message::SessionExpired => "Session expired".to_string(),
365            Message::AuthenticationFailed(service) => format!("Authentication failed: {}", service),
366            Message::JiraAuthenticateFailed => "Jira authenticate failed".to_string(),
367            Message::LoginFailed => "Login failed".to_string(),
368            Message::CredentialsNotSet => "Credentials not set!".to_string(),
369
370            // === API MESSAGES ===
371            Message::ApiConnectionFailed => "Failed to connect to API".to_string(),
372            Message::ApiAuthFailed => "API authentication failed".to_string(),
373            Message::ApiRequestFailed => "API request failed".to_string(),
374            Message::GitlabFetchFailed(error) => format!("[kasl] Failed to get GitLab events: {}", error),
375            Message::GitlabUserIdFailed(error) => format!("[kasl] Failed to get GitLab user ID: {}", error),
376            Message::JiraFetchFailed(error) => format!("[kasl] Failed to get Jira issues: {}", error),
377            Message::SiServerConfigNotFound => "SiServer configuration not found in config file.".to_string(),
378            Message::SiServerSessionFailed(error) => format!("[kasl] Failed to get SiServer session for rest dates: {}", error),
379            Message::SiServerRestDatesFailed(error) => format!("[kasl] Failed to request rest dates: {}", error),
380            Message::SiServerRestDatesParsingFailed(error) => format!("[kasl] Failed to parse rest dates response: {}", error),
381
382            // === DATABASE MESSAGES ===
383            Message::DbConnectionFailed => "Failed to connect to database".to_string(),
384            Message::DbQueryFailed => "Database query failed".to_string(),
385            Message::DbMigrationFailed => "Database migration failed".to_string(),
386            Message::DatabaseOperationFailed { operation, error } => {
387                format!("Database operation '{}' failed (continuing monitoring): {}", operation, error)
388            },
389            Message::NoIdSet => "No ID set".to_string(),
390
391            // === FILE SYSTEM MESSAGES ===
392            Message::FileNotFound => "File not found".to_string(),
393            Message::FileReadError => "Failed to read file".to_string(),
394            Message::FileWriteError => "Failed to write file".to_string(),
395            Message::InvalidPidFileContent => "Invalid PID file content".to_string(),
396            Message::DataStoragePathError => "DataStorage get_path error".to_string(),
397
398            // === SYSTEM/PATH MESSAGES ===
399            Message::PathConfigured => "PATH successfully configured for system-wide access".to_string(),
400            Message::PathConfigWarning { error } => format!("Warning: Could not configure PATH automatically. {}\nYou may need to run as administrator or manually add kasl to your PATH.", error),
401            Message::PathQueryFailed(status) => format!("Failed to query PATH from registry: {:?}", status),
402            Message::PathSetFailed => "Failed to set PATH in registry".to_string(),
403            Message::PathRegistryQueryError { status } => format!("Registry query failed (exit code: {})", status),
404            Message::PathRegistryUpdateError { status, stderr } => {
405                if stderr.trim().is_empty() {
406                    format!("Registry update failed (exit code: {})", status)
407                } else {
408                    format!("Registry update failed (exit code: {}): {}", status, stderr.trim())
409                }
410            },
411            Message::FailedToJoinPaths => "Failed to join paths".to_string(),
412            Message::FailedToExecuteRegQuery => "Failed to execute reg query".to_string(),
413            Message::FailedToParseRegOutput => "Failed to parse reg query output".to_string(),
414            Message::FailedToGetPathFromReg => "Failed to get PATH value from reg query".to_string(),
415            Message::FailedToExecuteRegSet => "Failed to execute reg set".to_string(),
416            Message::FailedToOpenProcess(code) => format!("Failed to open process: error code {}", code),
417            Message::FailedToTerminateProcess(code) => format!("Failed to terminate process: error code {}", code),
418            Message::ProcessNotFound => "Process doesn't exist".to_string(),
419            Message::ProcessTerminationNotSupported => "Process termination not supported on this platform".to_string(),
420
421            // === PRODUCTIVITY MESSAGES ===
422            Message::MonthlyProductivity(percentage) => format!("Monthly work productivity: {:.1}%", percentage),
423            Message::LowProductivityWarning { current, threshold, needed_break_minutes } => {
424                format!(
425                    "🔴 LOW PRODUCTIVITY: {:.1}% (minimum: {:.1}%)\n   To reach minimum productivity, add a {} minute break\n   Commands: kasl breaks -m {} (automatic) or kasl breaks (choose time)",
426                    current, threshold, needed_break_minutes, needed_break_minutes
427                )
428            },
429            Message::ProductivityTooLowToSend { current, threshold, needed_break_minutes } => {
430                format!(
431                    "Cannot send report: productivity {:.1}% is below minimum {:.1}%\nAdd a break using: kasl breaks -m {}",
432                    current, threshold, needed_break_minutes
433                )
434            },
435            Message::BreakCreated { start_time, end_time, duration_minutes } => {
436                format!("Break created: {} - {} ({} minutes)", start_time, end_time, duration_minutes)
437            },
438            Message::BreakCreateFailed(error) => format!("Failed to create break: {}", error),
439            Message::BreakSuggestionCommand { auto_minutes } => {
440                format!("Run 'kasl breaks -m {}' to automatically place break", auto_minutes)
441            },
442            Message::BreakInteractivePrompt => "Choose break placement interactively".to_string(),
443            Message::BreakDurationPrompt { min_duration, max_duration } => {
444                format!("Enter break duration ({}-{} minutes):", min_duration, max_duration)
445            },
446            Message::BreakPlacementOptions => "Select break placement:".to_string(),
447            Message::BreakOptionSelected(option) => format!("Selected option {}", option),
448            Message::BreakConflictsWithPauses => "Break conflicts with existing pauses".to_string(),
449            Message::NoValidBreakPlacement => "No valid placement found for break".to_string(),
450            Message::ProductivityRecalculated(percentage) => format!("Productivity recalculated: {:.1}%", percentage),
451
452            // === ENCRYPTION/SECRET MESSAGES ===
453            Message::EncryptionKeyMustBeSet => "ENCRYPTION_KEY must be set".to_string(),
454            Message::EncryptionIvMustBeSet => "ENCRYPTION_IV must be set".to_string(),
455
456            // === PROMPTS ===
457            Message::PromptTaskName => "Enter task name (multi-line paste OK)".to_string(),
458            Message::TaskNameMergedFromPaste => "Merged pasted lines into the task name.".to_string(),
459            Message::PromptTaskComment => "Enter comment".to_string(),
460            Message::PromptTaskCompleteness => "Enter completeness".to_string(),
461            Message::PromptGitlabToken => "Enter your GitLab private token".to_string(),
462            Message::PromptGitlabUrl => "Enter the GitLab API URL".to_string(),
463            Message::PromptJiraLogin => "Enter your Jira login".to_string(),
464            Message::PromptJiraUrl => "Enter the Jira API URL".to_string(),
465            Message::PromptJiraPassword => "Enter your Jira password".to_string(),
466            Message::PromptSiLogin => "Enter your SiServer login".to_string(),
467            Message::PromptSiAuthUrl => "Enter your SiServer login URL".to_string(),
468            Message::PromptSiApiUrl => "Enter the SiServer API URL".to_string(),
469            Message::PromptSiPassword => "Enter your SiServer password".to_string(),
470            Message::PromptMinPauseDuration => "Enter minimum pause duration (minutes)".to_string(),
471            Message::PromptPauseThreshold => "Enter pause threshold (seconds)".to_string(),
472            Message::PromptPollInterval => "Enter poll interval (milliseconds)".to_string(),
473            Message::PromptActivityThreshold => "Enter activity threshold (seconds)".to_string(),
474            Message::PromptMinProductivityThreshold => "Enter minimum productivity threshold (%)".to_string(),
475            Message::PromptWorkdayHours => "Enter expected workday duration (hours)".to_string(),
476            Message::PromptMinWorkdayFraction => "Enter minimum workday fraction before suggesting breaks (0.0-1.0)".to_string(),
477            Message::PromptMinBreakDuration => "Enter minimum break duration (minutes)".to_string(),
478            Message::PromptMaxBreakDuration => "Enter maximum break duration (minutes)".to_string(),
479            Message::PromptServerApiUrl => "Enter server API URL".to_string(),
480            Message::PromptServerAuthToken => "Enter server auth token".to_string(),
481            Message::PromptConfirmDelete => "Are you sure you want to delete this item?".to_string(),
482            Message::PromptSelectOptions => "Select options".to_string(),
483            Message::PromptSelectModules => "Select nodes to configure".to_string(),
484            Message::PromptSelectTasks => "Select tasks".to_string(),
485            Message::PromptSelectTasksToEdit => "Select tasks to edit".to_string(),
486            Message::PromptSelectTasksToImport => "Select tasks to import".to_string(),
487            Message::PromptSelectTasksToIgnore => "Select tasks to ignore (optional)".to_string(),
488            Message::PromptSelectIgnoreNamesToRemove => "Select ignore names to remove (optional)".to_string(),
489            Message::PromptAddIgnoreName => "Add ignore name (empty to finish)".to_string(),
490
491            // === GENERAL MESSAGES ===
492            Message::OperationCompleted => "Operation completed successfully".to_string(),
493            Message::OperationCancelled => "Operation cancelled".to_string(),
494            Message::DataExported => "Data exported successfully".to_string(),
495            Message::BackupCreated => "Backup created successfully".to_string(),
496            Message::InvalidInput => "Invalid input provided".to_string(),
497            Message::PermissionDenied => "Permission denied".to_string(),
498
499            // === ERROR LOGGING ===
500            Message::ErrorSendingEvents(error) => format!("[kasl] Error sending events: {}", error),
501            Message::ErrorSendingMonthlyReport(error) => format!("[kasl] Error sending monthly report: {}", error),
502            Message::ErrorInRdevListener(error) => format!("Error in rdev listener: {:?}", error),
503            Message::ErrorRequestingRestDates(error) => format!("Error requesting rest dates: {}", error),
504
505            // === SPECIFIC UI MESSAGES ===
506            Message::SelectingTask(name) => format!("Selected task: {}", name),
507            Message::SelectedTaskFormat(name, completeness) => format!("{} - {}%", name, completeness),
508
509            // === MIGRATION MESSAGES ===
510            Message::MigrationsFound(count) => format!("Found {} pending database migrations", count),
511            Message::RunningMigration(version, name) => format!("Running migration v{}: {}", version, name),
512            Message::MigrationCompleted(version) => format!("✓ Migration v{} completed", version),
513            Message::MigrationFailed(version, error) => format!("✗ Migration v{} failed: {}", version, error),
514            Message::AllMigrationsCompleted => "All database migrations completed successfully".to_string(),
515            Message::DatabaseVersion(version) => format!("Current database version: {}", version),
516            Message::DatabaseUpToDate => "Database schema is up to date".to_string(),
517            Message::DatabaseNeedsUpdate => "Database schema needs to be updated".to_string(),
518            Message::MigrationHistory => "Migration history:".to_string(),
519            Message::NothingToRollback => "Nothing to rollback".to_string(),
520            Message::RollingBack(from, to) => format!("Rolling back from v{} to v{}", from, to),
521            Message::RollbackCompleted(version) => format!("Rollback to v{} completed", version),
522        };
523
524        write!(f, "{}", text)
525    }
526}