//! Auto-detection of projects from current working directory
//!
//! This module provides intelligent project detection by:
//! 1. Searching for .project/{config_filename} in CWD and parent directories
//! 2. Reading project name from TOML configuration
//! 3. Caching last used project for quick access
//!
//! # Examples
//! ```no_run
//! use tools_shared::detect_project_from_cwd;
//!
//! if let Some(project) = detect_project_from_cwd("config.toml") {
//!     println!("Detected project: {}", project.name);
//!     println!("Root path: {}", project.root_path.display());
//! }
//! ```

use crate::xdg::{ensure_dir, tool_cache_dir};
use std::path::{Path, PathBuf};

/// Detected project information
#[derive(Debug, Clone)]
pub struct DetectedProject {
    /// Project name from config
    pub name: String,
    /// Path to configuration file (.project/lifecycle.toml)
    pub config_path: PathBuf,
    /// Root path of project (parent of .project/)
    pub root_path: PathBuf,
}

/// Auto-detect project from current working directory
///
/// Searches for configuration file (.project/{config_filename}) in CWD and parent directories.
///
/// # Arguments
/// * `config_filename` - Configuration filename (e.g., "config.toml", "tracking.toml")
///
/// # Returns
/// Some(DetectedProject) if found, None otherwise
///
/// # Examples
/// ```no_run
/// use tools_shared::detect_project_from_cwd;
///
/// if let Some(project) = detect_project_from_cwd("config.toml") {
///     println!("Project: {}", project.name);
/// }
/// ```
pub fn detect_project_from_cwd(config_filename: &str) -> Option<DetectedProject> {
    let cwd = std::env::current_dir().ok()?;
    detect_project_from_path(cwd, config_filename)
}

/// Auto-detect project from specific path
///
/// Searches upward from given path for .project/{config_filename}
///
/// # Arguments
/// * `path` - Starting path to search from
/// * `config_filename` - Configuration filename
///
/// # Returns
/// Some(DetectedProject) if found, None otherwise
pub fn detect_project_from_path<P: AsRef<Path>>(
    path: P,
    config_filename: &str,
) -> Option<DetectedProject> {
    let mut current = path.as_ref().to_path_buf();

    loop {
        // Try .project/
        let project_tools_config = current.join(".project").join(config_filename);
        if project_tools_config.exists() {
            if let Ok(project_name) = read_project_name(&project_tools_config) {
                return Some(DetectedProject {
                    name: project_name,
                    config_path: project_tools_config,
                    root_path: current,
                });
            }
        }

        // Try .vapora/ (VAPORA platform compatibility)
        let vapora_config = current.join(".vapora").join(config_filename);
        if vapora_config.exists() {
            if let Ok(project_name) = read_project_name(&vapora_config) {
                return Some(DetectedProject {
                    name: project_name,
                    config_path: vapora_config,
                    root_path: current,
                });
            }
        }

        // Move to parent directory
        if !current.pop() {
            break;
        }
    }

    None
}

/// Load last used project ID from cache
///
/// # Arguments
/// * `tool_name` - Name of the tool (e.g., "project-lifecycle")
///
/// # Returns
/// Some(project_id) if cached, None otherwise
pub fn load_last_project(tool_name: &str) -> Option<String> {
    let cache_file = tool_cache_dir(tool_name).join("last_project");
    std::fs::read_to_string(cache_file).ok()
}

/// Save last used project ID to cache
///
/// # Arguments
/// * `tool_name` - Name of the tool
/// * `project_id` - Project ID to cache
///
/// # Errors
/// Returns error if cache cannot be written
pub fn save_last_project(tool_name: &str, project_id: &str) -> std::io::Result<()> {
    let cache_dir = tool_cache_dir(tool_name);
    ensure_dir(&cache_dir)?;

    let cache_file = cache_dir.join("last_project");
    std::fs::write(cache_file, project_id)
}

/// Read project name from TOML configuration
/// Expects: [project] section with name = "..." field
fn read_project_name(config_path: &Path) -> Result<String, Box<dyn std::error::Error>> {
    let content = std::fs::read_to_string(config_path)?;

    // Simple TOML parsing for project.name field
    for line in content.lines() {
        let line = line.trim();
        if line.starts_with("name") && line.contains('=') {
            // Extract value between quotes
            if let Some(start) = line.find('"') {
                if let Some(end) = line[start + 1..].find('"') {
                    return Ok(line[start + 1..start + 1 + end].to_string());
                }
            }
        }
    }

    Err("project.name not found in config".into())
}

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

    #[test]
    fn test_detect_project_from_path() {
        let temp = TempDir::new().expect("Failed to create temp dir");
        let project_root = temp.path();

        // Create .project/test.toml
        let config_dir = project_root.join(".project");
        std::fs::create_dir(&config_dir).expect("Failed to create dir");

        let config_content = r#"
[project]
name = "test-project"
description = "Test project"
"#;
        let config_file = config_dir.join("test.toml");
        std::fs::write(&config_file, config_content).expect("Failed to write config");

        // Test detection
        let detected =
            detect_project_from_path(project_root, "test.toml").expect("Project not detected");

        assert_eq!(detected.name, "test-project");
        assert_eq!(detected.config_path, config_file);
        assert_eq!(detected.root_path, project_root);
    }

    #[test]
    fn test_detect_project_with_vapora() {
        let temp = TempDir::new().expect("Failed to create temp dir");
        let project_root = temp.path();

        // Create .vapora/test.toml
        let config_dir = project_root.join(".vapora");
        std::fs::create_dir(&config_dir).expect("Failed to create dir");

        let config_content = r#"
[project]
name = "vapora-project"
"#;
        let config_file = config_dir.join("test.toml");
        std::fs::write(&config_file, config_content).expect("Failed to write config");

        // Test detection
        let detected =
            detect_project_from_path(project_root, "test.toml").expect("Project not detected");

        assert_eq!(detected.name, "vapora-project");
    }

    #[test]
    fn test_detect_project_not_found() {
        let temp = TempDir::new().expect("Failed to create temp dir");
        let result = detect_project_from_path(temp.path(), "nonexistent.toml");
        assert!(result.is_none());
    }

    #[test]
    fn test_save_and_load_last_project() {
        use crate::xdg::tool_cache_dir;

        let tool_name = "test-tool-xyz";
        let project_id = "my-test-project";

        // Clean up any existing cache
        let _ = std::fs::remove_dir_all(tool_cache_dir(tool_name));

        // Save
        save_last_project(tool_name, project_id).expect("Failed to save project");

        // Load
        let loaded = load_last_project(tool_name).expect("Failed to load project");
        assert_eq!(loaded, project_id);

        // Cleanup
        let _ = std::fs::remove_dir_all(tool_cache_dir(tool_name));
    }
}
