/**
 * Command utilities for hiding console windows in production builds
 * 
 * This module provides utilities to configure std::process::Command instances
 * to hide console windows on Windows in production builds, preventing the
 * flash of command prompt windows when executing external processes.
 */

use std::process::Command;

// Windows-specific imports for hiding console window
#[cfg(target_os = "windows")]
use std::os::windows::process::CommandExt;

// Windows process creation flags
#[cfg(target_os = "windows")]
const CREATE_NO_WINDOW: u32 = 0x08000000;

/// Configure a Command to hide console window in production builds on Windows
/// 
/// This function applies the CREATE_NO_WINDOW flag to prevent console window
/// flashing when spawning processes from a GUI application. The console window
/// is only hidden in release builds to preserve debugging capabilities during
/// development.
/// 
/// # Arguments
/// * `cmd` - Mutable reference to the Command to configure
/// 
/// # Example
/// ```rust
/// use std::process::Command;
/// use crate::command_utils::configure_no_window;
/// 
/// let mut cmd = Command::new("python");
/// configure_no_window(&mut cmd);
/// let output = cmd.output();
/// ```
pub fn configure_no_window(cmd: &mut Command) {
    #[cfg(target_os = "windows")]
    {
        // Only hide console window in release builds
        // In debug builds, keep console visible for debugging
        #[cfg(not(debug_assertions))]
        {
            cmd.creation_flags(CREATE_NO_WINDOW);
            println!("Console window hidden for release build");
        }
        
        #[cfg(debug_assertions)]
        {
            println!("Console window visible for debug build");
        }
    }
    
    // On non-Windows platforms, this function does nothing
    #[cfg(not(target_os = "windows"))]
    {
        // No-op on non-Windows platforms
        let _ = cmd; // Suppress unused variable warning
    }
}

/// Create a new Command with console window hiding configured
/// 
/// This is a convenience function that creates a new Command and immediately
/// configures it to hide console windows in production builds.
/// 
/// # Arguments
/// * `program` - The program to execute
/// 
/// # Returns
/// A configured Command instance
/// 
/// # Example
/// ```rust
/// use crate::command_utils::create_hidden_command;
/// 
/// let mut cmd = create_hidden_command("python");
/// cmd.args(&["-c", "print('Hello, World!')"]);
/// let output = cmd.output();
/// ```
pub fn create_hidden_command<S: AsRef<std::ffi::OsStr>>(program: S) -> Command {
    let mut cmd = Command::new(program);
    configure_no_window(&mut cmd);
    cmd
}

/// Configure a Command for Python execution with console window hiding
/// 
/// This function configures a Command specifically for Python execution,
/// including proper encoding setup and console window hiding.
/// 
/// # Arguments
/// * `cmd` - Mutable reference to the Command to configure
/// * `project_root` - The working directory for the command
/// * `args` - Command line arguments
/// 
/// # Example
/// ```rust
/// use std::process::Command;
/// use std::path::Path;
/// use crate::command_utils::configure_python_command;
/// 
/// let mut cmd = Command::new("python");
/// let args = vec!["-c".to_string(), "print('Hello')".to_string()];
/// configure_python_command(&mut cmd, Path::new("."), &args);
/// ```
pub fn configure_python_command(cmd: &mut Command, project_root: &std::path::Path, args: &[String]) {
    cmd.current_dir(project_root);
    cmd.args(args);
    cmd.stdout(std::process::Stdio::piped());
    cmd.stderr(std::process::Stdio::piped());

    // Set environment variables for consistent encoding
    cmd.env("PYTHONIOENCODING", "utf-8");
    cmd.env("PYTHONUNBUFFERED", "1");

    // Platform-specific configurations
    if cfg!(target_os = "windows") {
        cmd.env("PYTHONUTF8", "1");
    }
    
    // Configure console window hiding
    configure_no_window(cmd);
}

/// Configure a Command for system operations (file/folder opening)
/// 
/// This function configures a Command for system operations like opening
/// files or folders, with appropriate console window hiding.
/// 
/// # Arguments
/// * `cmd` - Mutable reference to the Command to configure
/// 
/// # Example
/// ```rust
/// use std::process::Command;
/// use crate::command_utils::configure_system_command;
/// 
/// let mut cmd = Command::new("explorer");
/// cmd.arg("C:\\");
/// configure_system_command(&mut cmd);
/// ```
pub fn configure_system_command(cmd: &mut Command) {
    // Configure console window hiding for system commands
    configure_no_window(cmd);
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::process::Command;

    #[test]
    fn test_configure_no_window() {
        let mut cmd = Command::new("echo");
        configure_no_window(&mut cmd);
        // Test should not panic
    }

    #[test]
    fn test_create_hidden_command() {
        let cmd = create_hidden_command("echo");
        // Test should not panic and should return a Command
        assert_eq!(cmd.get_program(), "echo");
    }

    #[test]
    fn test_configure_python_command() {
        let mut cmd = Command::new("python");
        let args = vec!["-c".to_string(), "print('test')".to_string()];
        configure_python_command(&mut cmd, std::path::Path::new("."), &args);
        // Test should not panic
    }

    #[test]
    fn test_configure_system_command() {
        let mut cmd = Command::new("echo");
        configure_system_command(&mut cmd);
        // Test should not panic
    }
}

/// Utility macro for creating a hidden command with arguments
/// 
/// This macro provides a convenient way to create and configure a Command
/// with console window hiding in a single expression.
/// 
/// # Example
/// ```rust
/// use crate::command_utils::hidden_command;
/// 
/// let output = hidden_command!("python", "-c", "print('Hello')").output();
/// ```
#[macro_export]
macro_rules! hidden_command {
    ($program:expr $(, $arg:expr)*) => {
        {
            let mut cmd = $crate::command_utils::create_hidden_command($program);
            $(cmd.arg($arg);)*
            cmd
        }
    };
}

// Note: The hidden_command macro is automatically available when this module is imported
