subx_cli/commands/config_command.rs
1//! Configuration management command implementation with hierarchical settings.
2//!
3//! This module provides comprehensive configuration management capabilities
4//! through the `config` subcommand, enabling users to view, modify, and manage
5//! application settings across multiple configuration categories and sources.
6//! It supports hierarchical configuration with validation and type safety.
7//!
8//! # Configuration Architecture
9//!
10//! ## Configuration Categories
11//! - **General**: Basic application behavior and preferences
12//! - **AI Settings**: AI service providers, models, and API configuration
13//! - **Audio Processing**: Audio analysis and synchronization parameters
14//! - **Format Options**: Default output formats and conversion settings
15//! - **Cache Management**: Caching behavior and storage configuration
16//! - **Sync Settings**: Subtitle timing and synchronization options
17//!
18//! ## Configuration Sources (Priority Order)
19//! 1. **Command-line Arguments**: Highest priority, session-specific
20//! 2. **Environment Variables**: Runtime configuration overrides
21//! 3. **User Configuration**: Personal settings in user config directory
22//! 4. **Project Configuration**: Local project-specific settings
23//! 5. **System Configuration**: Global system-wide defaults
24//! 6. **Built-in Defaults**: Application default values
25//!
26//! # Supported Operations
27//!
28//! ## Set Operation
29//! - **Type Validation**: Ensure values match expected data types
30//! - **Range Checking**: Validate numeric values are within bounds
31//! - **Format Verification**: Check string values follow required patterns
32//! - **Dependency Validation**: Verify related settings are compatible
33//! - **Backup Creation**: Preserve previous values for rollback
34//!
35//! ## Get Operation
36//! - **Value Display**: Show current effective value
37//! - **Source Identification**: Indicate where value originates
38//! - **Type Information**: Display expected data type and constraints
39//! - **Default Comparison**: Show difference from built-in defaults
40//! - **Metadata Display**: Include help text and validation rules
41//!
42//! ## List Operation
43//! - **Categorized Display**: Group settings by functional area
44//! - **Source Indicators**: Show which settings are customized
45//! - **Value Formatting**: Display values in appropriate format
46//! - **Filter Options**: Support for category and status filtering
47//! - **Export Capability**: Generate configuration for sharing
48//!
49//! ## Reset Operation
50//! - **Backup Creation**: Automatic backup before reset
51//! - **Selective Reset**: Option to reset specific categories
52//! - **Confirmation Process**: Interactive confirmation for safety
53//! - **Recovery Information**: Instructions for backup restoration
54//!
55//! # Configuration Keys
56//!
57//! ## General Settings
58//! ```text
59//! general.enable_progress_bar # Boolean: Show progress indicators
60//! general.backup_enabled # Boolean: Automatic file backups
61//! general.task_timeout_seconds # Integer: Operation timeout in seconds
62//! ```
63//!
64//! ## AI Configuration
65//! ```text
66//! ai.provider # String: AI service provider
67//! ai.api_key # String: OpenAI API authentication
68//! ai.model # String: GPT model selection
69//! ai.max_tokens # Integer: Maximum response length
70//! ai.base_url # String: API endpoint URL
71//! ai.max_sample_length # Integer: Text sample size for analysis
72//! ai.temperature # Float: Response randomness control
73//! ai.retry_attempts # Integer: API request retry count
74//! ai.retry_delay_ms # Integer: Retry delay in milliseconds
75//! ```
76//!
77//! ## Audio Processing
78//! ```text
79//! audio.max_offset_seconds # Float: Maximum sync offset range
80//! audio.correlation_threshold # Float: Minimum correlation for sync
81//! audio.dialogue_threshold # Float: Speech detection sensitivity
82//! audio.min_dialogue_duration_ms # Integer: Minimum speech segment length
83//! audio.enable_dialogue_detection # Boolean: Advanced audio analysis
84//! ```
85//!
86//! # Examples
87//!
88//! ```rust,ignore
89//! use subx_cli::cli::{ConfigArgs, ConfigAction};
90//! use subx_cli::commands::config_command;
91//!
92//! // Set AI provider
93//! let set_args = ConfigArgs {
94//! action: ConfigAction::Set {
95//! key: "ai.provider".to_string(),
96//! value: "openai".to_string(),
97//! },
98//! };
99//! config_command::execute(set_args).await?;
100//!
101//! // Get current AI model
102//! let get_args = ConfigArgs {
103//! action: ConfigAction::Get {
104//! key: "ai.openai.model".to_string(),
105//! },
106//! };
107//! config_command::execute(get_args).await?;
108//! ```
109
110use crate::cli::{ConfigAction, ConfigArgs};
111use crate::config::ConfigService;
112use crate::error::{SubXError, SubXResult};
113
114/// Execute configuration management operations with validation and type safety.
115///
116/// This function provides the main entry point for all configuration management
117/// operations, including setting values, retrieving current configuration,
118/// listing all settings, and resetting to defaults. It includes comprehensive
119/// validation, error handling, and user-friendly output formatting.
120///
121/// # Operation Workflow
122///
123/// ## Set Operation
124/// 1. **Configuration Loading**: Load current configuration from all sources
125/// 2. **Key Validation**: Verify configuration key exists and is writable
126/// 3. **Value Parsing**: Convert string value to appropriate data type
127/// 4. **Constraint Checking**: Validate value meets all requirements
128/// 5. **Dependency Verification**: Check related settings compatibility
129/// 6. **Backup Creation**: Save current value for potential rollback
130/// 7. **Value Application**: Update configuration with new value
131/// 8. **Persistence**: Save updated configuration to appropriate file
132/// 9. **Confirmation**: Display success message with applied value
133///
134/// ## Get Operation
135/// 1. **Configuration Loading**: Load current effective configuration
136/// 2. **Key Resolution**: Locate requested configuration setting
137/// 3. **Source Identification**: Determine where value originates
138/// 4. **Value Formatting**: Format value for appropriate display
139/// 5. **Metadata Retrieval**: Gather type and constraint information
140/// 6. **Output Generation**: Create comprehensive information display
141///
142/// ## List Operation
143/// 1. **Configuration Loading**: Load all configuration settings
144/// 2. **Categorization**: Group settings by functional area
145/// 3. **Source Analysis**: Identify customized vs. default values
146/// 4. **Formatting**: Prepare values for tabular display
147/// 5. **Output Generation**: Create organized configuration overview
148///
149/// ## Reset Operation
150/// 1. **Current State Backup**: Create timestamped configuration backup
151/// 2. **User Confirmation**: Interactive confirmation for destructive operation
152/// 3. **Default Restoration**: Replace all settings with built-in defaults
153/// 4. **Validation**: Verify reset configuration is valid
154/// 5. **Persistence**: Save default configuration to user config file
155/// 6. **Confirmation**: Display reset completion and backup location
156///
157/// # Type System Integration
158///
159/// The configuration system provides strong typing with automatic conversion:
160/// - **Boolean Values**: "true", "false", "1", "0", "yes", "no"
161/// - **Integer Values**: Decimal notation with range validation
162/// - **Float Values**: Decimal notation with precision preservation
163/// - **String Values**: UTF-8 text with format validation where applicable
164/// - **Array Values**: JSON array format for complex configuration
165///
166/// # Validation Framework
167///
168/// Each configuration setting includes comprehensive validation:
169/// - **Type Constraints**: Must match expected data type
170/// - **Range Limits**: Numeric values within acceptable bounds
171/// - **Format Requirements**: String values matching required patterns
172/// - **Dependency Rules**: Related settings must be compatible
173/// - **Security Checks**: Sensitive values properly protected
174///
175/// # Arguments
176///
177/// * `args` - Configuration command arguments containing the specific
178/// operation to perform (set, get, list, or reset) along with any
179/// required parameters such as key names and values.
180///
181/// # Returns
182///
183/// Returns `Ok(())` on successful operation completion, or an error describing:
184/// - Configuration loading or parsing failures
185/// - Invalid configuration keys or malformed key paths
186/// - Type conversion or validation errors
187/// - File system access problems during persistence
188/// - User cancellation of destructive operations
189///
190/// # Error Categories
191///
192/// ## Configuration Errors
193/// - **Invalid Key**: Specified configuration key does not exist
194/// - **Type Mismatch**: Value cannot be converted to expected type
195/// - **Range Error**: Numeric value outside acceptable range
196/// - **Format Error**: String value doesn't match required pattern
197/// - **Dependency Error**: Value conflicts with related settings
198///
199/// ## System Errors
200/// - **File Access**: Cannot read or write configuration files
201/// - **Permission Error**: Insufficient privileges for operation
202/// - **Disk Space**: Insufficient space for configuration persistence
203/// - **Corruption**: Configuration file is damaged or invalid
204///
205/// # Security Considerations
206///
207/// - **Sensitive Values**: API keys and credentials are properly masked in output
208/// - **File Permissions**: Configuration files created with appropriate permissions
209/// - **Backup Protection**: Backup files inherit security settings
210/// - **Validation**: All input values sanitized and validated
211///
212/// # Examples
213///
214/// ```rust,ignore
215/// use subx_cli::cli::{ConfigArgs, ConfigAction};
216/// use subx_cli::commands::config_command;
217///
218/// // Configure AI service with API key
219/// let ai_setup = ConfigArgs {
220/// action: ConfigAction::Set {
221/// key: "ai.openai.api_key".to_string(),
222/// value: "sk-1234567890abcdef".to_string(),
223/// },
224/// };
225/// config_command::execute(ai_setup).await?;
226///
227/// // Adjust audio processing sensitivity
228/// let audio_tuning = ConfigArgs {
229/// action: ConfigAction::Set {
230/// key: "audio.correlation_threshold".to_string(),
231/// value: "0.85".to_string(),
232/// },
233/// };
234/// config_command::execute(audio_tuning).await?;
235///
236/// // View complete configuration
237/// let view_all = ConfigArgs {
238/// action: ConfigAction::List,
239/// };
240/// config_command::execute(view_all).await?;
241///
242/// // Reset to clean state
243/// let reset_config = ConfigArgs {
244/// action: ConfigAction::Reset,
245/// };
246/// config_command::execute(reset_config).await?;
247/// ```
248pub async fn execute(args: ConfigArgs, config_service: &dyn ConfigService) -> SubXResult<()> {
249 match args.action {
250 ConfigAction::Set { key, value } => {
251 config_service.set_config_value(&key, &value)?;
252 println!("✓ Configuration '{key}' set to '{value}'");
253 // Display the updated value to confirm
254 if let Ok(current) = config_service.get_config_value(&key) {
255 println!(" Current value: {current}");
256 }
257 if let Ok(path) = config_service.get_config_file_path() {
258 println!(" Saved to: {}", path.display());
259 }
260 }
261 ConfigAction::Get { key } => {
262 let value = config_service.get_config_value(&key)?;
263 println!("{value}");
264 }
265 ConfigAction::List => {
266 let config = config_service.get_config()?;
267 if let Ok(path) = config_service.get_config_file_path() {
268 println!("# Configuration file path: {}\n", path.display());
269 }
270 println!(
271 "{}",
272 toml::to_string_pretty(&config)
273 .map_err(|e| SubXError::config(format!("TOML serialization error: {e}")))?
274 );
275 }
276 ConfigAction::Reset => {
277 config_service.reset_to_defaults()?;
278 println!("Configuration reset to default values");
279 if let Ok(path) = config_service.get_config_file_path() {
280 println!("Default configuration saved to: {}", path.display());
281 }
282 }
283 }
284 Ok(())
285}
286
287/// Execute configuration management command with injected configuration service.
288///
289/// This function provides the new dependency injection interface for the config command,
290/// accepting a configuration service instead of loading configuration globally.
291///
292/// # Arguments
293///
294/// * `args` - Configuration command arguments
295/// * `config_service` - Configuration service providing access to settings
296///
297/// # Returns
298///
299/// Returns `Ok(())` on successful completion, or an error if the operation fails.
300pub async fn execute_with_config(
301 args: ConfigArgs,
302 config_service: std::sync::Arc<dyn ConfigService>,
303) -> SubXResult<()> {
304 match args.action {
305 ConfigAction::Set { key, value } => {
306 config_service.set_config_value(&key, &value)?;
307 println!("✓ Configuration '{key}' set to '{value}'");
308 // Display the updated value to confirm
309 if let Ok(current) = config_service.get_config_value(&key) {
310 println!(" Current value: {current}");
311 }
312 if let Ok(path) = config_service.get_config_file_path() {
313 println!(" Saved to: {}", path.display());
314 }
315 }
316 ConfigAction::Get { key } => {
317 let value = config_service.get_config_value(&key)?;
318 println!("{value}");
319 }
320 ConfigAction::List => {
321 let config = config_service.get_config()?;
322 if let Ok(path) = config_service.get_config_file_path() {
323 println!("# Configuration file path: {}\n", path.display());
324 }
325 println!(
326 "{}",
327 toml::to_string_pretty(&config)
328 .map_err(|e| SubXError::config(format!("TOML serialization error: {e}")))?
329 );
330 }
331 ConfigAction::Reset => {
332 config_service.reset_to_defaults()?;
333 println!("Configuration reset to default values");
334 if let Ok(path) = config_service.get_config_file_path() {
335 println!("Default configuration saved to: {}", path.display());
336 }
337 }
338 }
339 Ok(())
340}