//! Test helper utilities

use anyhow::Result;
use serde_json::Value;
use std::fs;
use std::path::Path;
use tempfile::TempDir;

/// Test feature manifest builder
pub struct TestFeatureBuilder {
    pub name: String,
    pub version: String,
    pub dependencies: Vec<String>,
    pub environment_vars: Vec<(String, String, bool)>, // (name, default, required)
}

impl TestFeatureBuilder {
    pub fn new(name: &str) -> Self {
        Self {
            name: name.to_string(),
            version: "0.1.0".to_string(),
            dependencies: Vec::new(),
            environment_vars: Vec::new(),
        }
    }

    pub fn with_dependency(mut self, dep: &str) -> Self {
        self.dependencies.push(dep.to_string());
        self
    }

    pub fn with_env_var(mut self, name: &str, default: &str, required: bool) -> Self {
        self.environment_vars.push((name.to_string(), default.to_string(), required));
        self
    }

    pub fn build_manifest(&self) -> String {
        let mut manifest = format!(
            r#"[feature]
name = "{}"
version = "{}"
source = "test"
description = "Test feature"
requires = []

[dependencies]
workspace = {:?}
external = []
"#,
            self.name, self.version, self.dependencies
        );

        if !self.environment_vars.is_empty() {
            manifest.push_str("\n");
            for (name, default, required) in &self.environment_vars {
                manifest.push_str(&format!(
                    "\n[[environment.variables]]\nname = \"{}\"\ndefault = \"{}\"\nrequired = {}\n",
                    name, default, required
                ));
            }
        }

        manifest
    }

    pub fn create_in_project(&self, project_root: &Path) -> Result<()> {
        let feature_dir = project_root.join("features").join(&self.name);
        fs::create_dir_all(&feature_dir)?;

        let manifest_path = feature_dir.join("feature.toml");
        fs::write(&manifest_path, self.build_manifest())?;

        Ok(())
    }
}

/// Assert that a file contains specific content
pub fn assert_file_contains(file_path: &Path, content: &str) -> Result<()> {
    let file_content = fs::read_to_string(file_path)?;
    assert!(file_content.contains(content),
           "File {} does not contain expected content: {}",
           file_path.display(), content);
    Ok(())
}

/// Assert that a JSON file has a specific value at a path
pub fn assert_json_value(file_path: &Path, json_path: &str, expected: &Value) -> Result<()> {
    let content = fs::read_to_string(file_path)?;
    let json: Value = serde_json::from_str(&content)?;

    // Simple path traversal (e.g., "dependencies.analytics")
    let parts: Vec<&str> = json_path.split('.').collect();
    let mut current = &json;

    for part in parts {
        current = current.get(part)
            .ok_or_else(|| anyhow::anyhow!("Path {} not found in JSON", json_path))?;
    }

    assert_eq!(current, expected, "JSON value at {} does not match expected", json_path);
    Ok(())
}

/// Create a mock feature registry
pub fn create_mock_registry(project_root: &Path) -> Result<()> {
    let registry_content = r#"
# Test Features Registry

[features]

[features.test-analytics]
description = "Test analytics system"
source = "test"
status = "available"
requires = []

[features.test-build]
description = "Test build system"
source = "test"
status = "available"
requires = []
"#;

    let registry_path = project_root.join("registry/features.toml");
    fs::write(&registry_path, registry_content)?;
    Ok(())
}
