//! Node selection logic for development mode

use crate::services::ProcessService;
use crate::types::{NodeEntry, ProjectConfig};

/// Information about a node to run
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct NodeToRun {
    /// Node name
    pub name: String,
    /// Path to the node package (e.g., "mecha10-nodes-motor-fake" or "nodes/custom")
    pub path: String,
    /// Whether this is a monorepo node (starts with "mecha10-nodes-")
    pub is_monorepo_node: bool,
}

impl NodeToRun {
    /// Create a new NodeToRun from NodeEntry
    pub fn from_config(node: &NodeEntry) -> Self {
        let is_monorepo = node.path.starts_with("mecha10-nodes-");
        Self {
            name: node.name.clone(),
            path: node.path.clone(),
            is_monorepo_node: is_monorepo,
        }
    }

    /// Get the binary path for this node
    ///
    /// Uses smart resolution to find the best binary location:
    /// - Framework dev mode: local build in target/
    /// - Production mode: globally installed binary (if available)
    /// - Fallback: local build
    ///
    /// Note: This method is no longer used by CLI (replaced by node-runner in Phase 2).
    /// Kept for testing purposes.
    #[allow(dead_code)]
    pub fn binary_path(&self, project_name: &str) -> String {
        ProcessService::resolve_node_binary(&self.name, self.is_monorepo_node, project_name)
    }

    /// Get command args for running this node
    ///
    /// Returns args based on whether we're using:
    /// - Global binary: no args (binary IS the node)
    /// - Local project build: ["node", "node_name"] subcommand
    ///
    /// Note: This method is no longer used by CLI (replaced by node-runner in Phase 2).
    /// Kept for testing purposes.
    #[allow(dead_code)]
    pub fn args(&self, project_name: &str) -> Vec<String> {
        if self.is_monorepo_node {
            // Check if we're using a global binary
            let binary_path = self.binary_path(project_name);

            // If the binary path doesn't start with "target/", it's a global binary
            // Global binaries don't need the "node" subcommand
            if !binary_path.starts_with("target/") {
                vec![]
            } else {
                // Local build uses "node" subcommand
                vec!["node".to_string(), self.name.clone()]
            }
        } else {
            vec![]
        }
    }
}

/// Get list of nodes to run based on configuration
///
/// # Arguments
///
/// * `requested_nodes` - Specific nodes requested by user (empty = all enabled)
/// * `project_config` - Project configuration
///
/// # Returns
///
/// List of nodes to run
pub fn get_nodes_to_run(requested_nodes: &[String], project_config: &ProjectConfig) -> Vec<NodeToRun> {
    // Collect all nodes from config
    let mut all_nodes: Vec<NodeEntry> = Vec::new();
    all_nodes.extend(project_config.nodes.drivers.clone());
    all_nodes.extend(project_config.nodes.custom.clone());

    // If specific nodes requested, filter to those
    let nodes_to_run: Vec<NodeEntry> = if requested_nodes.is_empty() {
        // Use all enabled nodes
        all_nodes.into_iter().filter(|n| n.enabled).collect()
    } else {
        // Use only requested nodes (ignore enabled status)
        all_nodes
            .into_iter()
            .filter(|n| requested_nodes.contains(&n.name))
            .collect()
    };

    // Convert to NodeToRun
    nodes_to_run.iter().map(NodeToRun::from_config).collect()
}

/// Get list of all available node names
pub fn get_available_node_names(project_config: &ProjectConfig) -> Vec<String> {
    let mut names = Vec::new();

    for node in &project_config.nodes.drivers {
        names.push(node.name.clone());
    }
    for node in &project_config.nodes.custom {
        names.push(node.name.clone());
    }

    names
}

/// Get list of enabled node names
#[allow(dead_code)] // Tested, planned for future use
pub fn get_enabled_node_names(project_config: &ProjectConfig) -> Vec<String> {
    let mut names = Vec::new();

    for node in &project_config.nodes.drivers {
        if node.enabled {
            names.push(node.name.clone());
        }
    }
    for node in &project_config.nodes.custom {
        if node.enabled {
            names.push(node.name.clone());
        }
    }

    names
}
