//! XDG Base Directory support for Tools ecosystem
//!
//! Provides standard directories for tool-specific configuration and data storage.
//! Follows XDG Base Directory Specification on Linux and macOS.
//!
//! # Examples
//! ```no_run
//! use tools_shared::tool_data_dir;
//!
//! let data_dir = tool_data_dir("my-tool");
//! println!("Data directory: {}", data_dir.display());
//! // Outputs: ~/.local/share/tools/my-tool or $XDG_DATA_HOME/tools/my-tool
//! ```

use std::path::PathBuf;

/// Get XDG data directory for a tool
///
/// Returns: `$XDG_DATA_HOME/tools/{tool_name}/` or `~/.local/share/tools/{tool_name}/`
///
/// # Arguments
/// * `tool_name` - Name of the tool (e.g., "project-lifecycle")
///
/// # Panics
/// Panics if home directory cannot be determined
pub fn tool_data_dir(tool_name: &str) -> PathBuf {
    dirs::data_dir()
        .map(|d| d.join("tools").join(tool_name))
        .unwrap_or_else(|| {
            let home = std::env::var("HOME").unwrap_or_else(|_| ".".to_string());
            PathBuf::from(home)
                .join(".local/share/tools")
                .join(tool_name)
        })
}

/// Get XDG config directory for a tool
///
/// Returns: `$XDG_CONFIG_HOME/tools/{tool_name}/` or `~/.config/tools/{tool_name}/`
///
/// # Arguments
/// * `tool_name` - Name of the tool (e.g., "project-lifecycle")
///
/// # Panics
/// Panics if home directory cannot be determined
pub fn tool_config_dir(tool_name: &str) -> PathBuf {
    dirs::config_dir()
        .map(|d| d.join("tools").join(tool_name))
        .unwrap_or_else(|| {
            let home = std::env::var("HOME").unwrap_or_else(|_| ".".to_string());
            PathBuf::from(home).join(".config/tools").join(tool_name)
        })
}

/// Get XDG cache directory for a tool
///
/// Returns: `$XDG_CACHE_HOME/tools/{tool_name}/` or `~/.cache/tools/{tool_name}/`
///
/// # Arguments
/// * `tool_name` - Name of the tool (e.g., "project-lifecycle")
///
/// # Panics
/// Panics if home directory cannot be determined
pub fn tool_cache_dir(tool_name: &str) -> PathBuf {
    dirs::cache_dir()
        .map(|d| d.join("tools").join(tool_name))
        .unwrap_or_else(|| {
            let home = std::env::var("HOME").unwrap_or_else(|_| ".".to_string());
            PathBuf::from(home).join(".cache/tools").join(tool_name)
        })
}

/// Ensure directory exists, creating it if necessary
///
/// # Arguments
/// * `path` - Path to directory
///
/// # Errors
/// Returns error if directory cannot be created
///
/// # Examples
/// ```no_run
/// use tools_shared::{tool_data_dir, ensure_dir};
///
/// let dir = tool_data_dir("my-tool");
/// ensure_dir(&dir).expect("Failed to create directory");
/// ```
pub fn ensure_dir(path: &PathBuf) -> std::io::Result<PathBuf> {
    if !path.exists() {
        std::fs::create_dir_all(path)?;
    }
    Ok(path.clone())
}

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

    #[test]
    fn test_tool_data_dir() {
        let data_dir = tool_data_dir("test-tool");
        assert!(data_dir.to_string_lossy().contains("test-tool"));
        assert!(
            data_dir.to_string_lossy().contains("tools")
                || data_dir.to_string_lossy().contains(".local")
        );
    }

    #[test]
    fn test_tool_config_dir() {
        let config_dir = tool_config_dir("test-tool");
        assert!(config_dir.to_string_lossy().contains("test-tool"));
        assert!(
            config_dir.to_string_lossy().contains("tools")
                || config_dir.to_string_lossy().contains(".config")
        );
    }

    #[test]
    fn test_tool_cache_dir() {
        let cache_dir = tool_cache_dir("test-tool");
        assert!(cache_dir.to_string_lossy().contains("test-tool"));
        assert!(
            cache_dir.to_string_lossy().contains("tools")
                || cache_dir.to_string_lossy().contains(".cache")
        );
    }

    #[test]
    fn test_ensure_dir_creates_directory() {
        use tempfile::TempDir;

        let temp = TempDir::new().expect("Failed to create temp dir");
        let test_dir = temp.path().join("test").join("nested").join("dir");

        ensure_dir(&test_dir).expect("Failed to ensure dir");
        assert!(test_dir.exists());
    }

    #[test]
    fn test_ensure_dir_existing() {
        use tempfile::TempDir;

        let temp = TempDir::new().expect("Failed to create temp dir");
        let test_dir = temp.path().join("test");

        std::fs::create_dir(&test_dir).expect("Failed to create dir");
        ensure_dir(&test_dir).expect("Failed to ensure dir");
        assert!(test_dir.exists());
    }
}
