//! Filesystem abstraction for testing.

mod std_fs;

pub use std_fs::StdFs;

use std::io;
use std::path::{Path, PathBuf};

/// Abstraction over filesystem operations for testing.
///
/// Allows mocking filesystem operations in tests.
pub trait Fs: Send + Sync {
    /// Check if a path exists.
    fn exists(&self, path: &Path) -> bool;

    /// Check if a path is a file.
    fn is_file(&self, path: &Path) -> bool;

    /// Check if a path is a directory.
    fn is_dir(&self, path: &Path) -> bool;

    /// Create a directory and all its parents.
    ///
    /// # Errors
    ///
    /// Returns an error if the directory cannot be created.
    fn create_dir_all(&self, path: &Path) -> io::Result<()>;

    /// Read directory entries.
    ///
    /// Returns an empty vector if the directory doesn't exist or cannot be read.
    fn read_dir(&self, path: &Path) -> Vec<PathBuf> {
        if !self.is_dir(path) {
            return Vec::new();
        }
        std::fs::read_dir(path)
            .map(|entries| {
                entries
                    .filter_map(Result::ok)
                    .map(|entry| entry.path())
                    .collect()
            })
            .unwrap_or_default()
    }

    /// Get path metadata.
    fn metadata(&self, path: &Path) -> Option<std::fs::Metadata> {
        std::fs::metadata(path).ok()
    }
}
