//! Common test utilities for dirigent_tools.
//!
//! This module provides shared test utilities used across all test files.

use std::path::{Path, PathBuf};
use tempfile::TempDir;

/// Create a temporary directory for testing.
///
/// The directory is automatically cleaned up when the TempDir is dropped.
pub fn create_temp_dir() -> TempDir {
    tempfile::tempdir().expect("Failed to create temp directory")
}

/// Create a temporary directory with a specific prefix.
pub fn create_temp_dir_with_prefix(prefix: &str) -> TempDir {
    tempfile::Builder::new()
        .prefix(prefix)
        .tempdir()
        .expect("Failed to create temp directory with prefix")
}

/// Create a file in a directory with given content.
pub fn create_test_file(dir: &Path, filename: &str, content: &str) -> PathBuf {
    let file_path = dir.join(filename);
    std::fs::write(&file_path, content).expect("Failed to write test file");
    file_path
}

/// Read a file and return its content.
pub fn read_file_content(path: &Path) -> String {
    std::fs::read_to_string(path).expect("Failed to read file")
}

/// Create a sandboxed test environment with configured allowed roots.
pub struct SandboxedTestEnv {
    // RAII: TempDir must be kept alive to prevent premature cleanup
    pub _temp_dir: TempDir,
    pub allowed_root: PathBuf,
    pub blocked_dir: PathBuf,
    pub outside_dir: TempDir,
}

impl SandboxedTestEnv {
    /// Create a new sandboxed test environment.
    pub fn new() -> Self {
        let temp_dir = create_temp_dir();
        let allowed_root = temp_dir.path().to_path_buf();
        let blocked_dir = allowed_root.join("blocked");
        let outside_dir = create_temp_dir_with_prefix("outside");

        std::fs::create_dir_all(&blocked_dir).expect("Failed to create blocked directory");

        Self {
            _temp_dir: temp_dir,
            allowed_root,
            blocked_dir,
            outside_dir,
        }
    }

    /// Create a file inside the allowed root.
    pub fn create_allowed_file(&self, filename: &str, content: &str) -> PathBuf {
        create_test_file(&self.allowed_root, filename, content)
    }

    /// Create a file outside the allowed root.
    pub fn create_outside_file(&self, filename: &str, content: &str) -> PathBuf {
        create_test_file(self.outside_dir.path(), filename, content)
    }
}

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

    #[test]
    fn test_create_temp_dir() {
        let temp_dir = create_temp_dir();
        assert!(temp_dir.path().exists());
    }

    #[test]
    fn test_create_test_file() {
        let temp_dir = create_temp_dir();
        let file_path = create_test_file(temp_dir.path(), "test.txt", "Hello, world!");
        assert!(file_path.exists());
        assert_eq!(read_file_content(&file_path), "Hello, world!");
    }

    #[test]
    fn test_sandboxed_test_env() {
        let env = SandboxedTestEnv::new();
        assert!(env.allowed_root.exists());
        assert!(env.blocked_dir.exists());
        assert!(env.outside_dir.path().exists());

        let allowed_file = env.create_allowed_file("test.txt", "allowed");
        let outside_file = env.create_outside_file("test.txt", "outside");

        assert!(allowed_file.exists());
        assert!(outside_file.exists());
        assert_ne!(
            allowed_file.parent().unwrap(),
            outside_file.parent().unwrap()
        );
    }
}
