//! Project resolution helper
//!
//! Handles auto-detection and selection of projects using shared utilities.

use crate::ui_config;
use anyhow::{anyhow, Result};
use syntaxis_core::persistence::{Database, SqliteDatabase};
use tools_shared::{
    detect_project_from_cwd, find_global_db_path, load_last_project, save_last_project,
    select_project, SelectableProject,
};

/// Resolve project ID with intelligent fallback chain
///
/// Resolution order:
/// 1. Explicit --project flag (provided)
/// 2. Auto-detect from CWD (.project/lifecycle.toml)
/// 3. Load from cache (last used project)
/// 4. Interactive selector (choose from all projects in global DB)
#[allow(dead_code)]
pub async fn resolve_project(project_arg: Option<&str>) -> Result<String> {
    // 1. Explicit --project flag
    if let Some(name) = project_arg {
        return Ok(name.to_string());
    }

    // 2. Auto-detect from CWD
    if let Some(detected) = detect_project_from_cwd("config.toml") {
        eprintln!("📍 Auto-detected project: {}", detected.name);
        // Save as last project
        let _ = save_last_project("workspace", &detected.name);
        return Ok(detected.name);
    }

    // 3. Load from cache
    if let Some(last_project) = load_last_project("workspace") {
        eprintln!("📌 Using last project: {}", last_project);
        return Ok(last_project);
    }

    // 4. Interactive selector
    eprintln!("🔍 No project detected. Searching database...");
    select_project_interactive().await
}

/// Show interactive project selector
#[allow(dead_code)]
async fn select_project_interactive() -> Result<String> {
    // Open global database
    let global_path = find_global_db_path("workspace");
    let global_db_path_str = global_path.to_string_lossy().to_string();
    let db = SqliteDatabase::new(&global_db_path_str)
        .await
        .map_err(|e| anyhow!("Failed to open database: {}", e))?;

    // Load all projects
    let projects = db
        .list_projects()
        .await
        .map_err(|e| anyhow!("Failed to load projects: {}", e))?;

    if projects.is_empty() {
        let app_name = ui_config::get_app_name();
        return Err(anyhow!(
            "No projects found in database. Run '{} init' first.",
            app_name
        ));
    }

    // Convert to selectable projects
    let selectable: Vec<SelectableProject> = projects
        .into_iter()
        .map(|p| SelectableProject {
            id: p.id.clone(),
            name: p.name,
            path: None,
            metadata: Some(format!("Phase: {:?}", p.current_phase)),
        })
        .collect();

    // Show selector
    let selected_id = select_project(selectable, "Select a project:", None)
        .map_err(|e| anyhow!("Selection failed: {}", e))?;

    // Save as last project
    save_last_project("workspace", &selected_id)?;

    Ok(selected_id)
}

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

    #[test]
    fn test_resolve_project_explicit() {
        // Test explicit project flag
        let result = tokio::runtime::Runtime::new()
            .unwrap()
            .block_on(resolve_project(Some("my-project")));

        assert!(result.is_ok());
        assert_eq!(result.unwrap(), "my-project");
    }

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

        // Create .project/lifecycle.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("config.toml");
        std::fs::write(&config_file, config_content).expect("Failed to write config");

        // Change to project directory
        let original_cwd = std::env::current_dir().unwrap();
        std::env::set_current_dir(project_root).expect("Failed to change dir");

        let result = tokio::runtime::Runtime::new()
            .unwrap()
            .block_on(resolve_project(None));

        // Restore original directory
        let _ = std::env::set_current_dir(original_cwd);

        // Auto-detect should find the project
        assert!(result.is_ok());
        assert_eq!(result.unwrap(), "test-project");
    }
}
