//! Centralized path definitions for the CLI
//!
//! All hardcoded paths should be defined here to ensure consistency
//! and make it easy to update paths across the codebase.
//!
//! # Organization
//!
//! - **Project paths**: Paths relative to project root (mecha10.json location)
//! - **User paths**: Paths in user's home directory (~/.mecha10)
//! - **Docker paths**: Paths used inside Docker containers
//! - **Framework paths**: Paths within the mecha10 framework source

// Allow dead code during migration - paths will be used incrementally
#![allow(dead_code)]

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

// =============================================================================
// Project Structure - Paths relative to project root
// =============================================================================

/// Project configuration file
pub const PROJECT_CONFIG: &str = "mecha10.json";

/// Project directories
pub mod project {
    /// Node source code directory
    pub const NODES_DIR: &str = "nodes";

    /// Driver source code directory
    pub const DRIVERS_DIR: &str = "drivers";

    /// Types directory
    pub const TYPES_DIR: &str = "types";

    /// Behavior trees directory
    pub const BEHAVIORS_DIR: &str = "behaviors";

    /// Assets directory
    pub const ASSETS_DIR: &str = "assets";

    /// Assets images subdirectory
    pub const ASSETS_IMAGES_DIR: &str = "assets/images";

    /// Models directory (ONNX models, etc.)
    pub const MODELS_DIR: &str = "models";

    /// Logs directory
    pub const LOGS_DIR: &str = "logs";

    /// Simulation directory
    pub const SIMULATION_DIR: &str = "simulation";

    /// Simulation models directory
    pub const SIMULATION_MODELS_DIR: &str = "simulation/models";

    /// Simulation environments directory
    pub const SIMULATION_ENVIRONMENTS_DIR: &str = "simulation/environments";

    /// Get path to a model's config file
    pub fn model_config(model_name: &str) -> String {
        format!("simulation/models/{}/model.json", model_name)
    }

    /// Get path to an environment's config file
    pub fn environment_config(env_name: &str) -> String {
        format!("simulation/environments/{}/environment.json", env_name)
    }

    /// Simulation Godot project directory
    pub const SIMULATION_GODOT_DIR: &str = "simulation/godot";

    /// Cargo build target directory
    pub const TARGET_DIR: &str = "target";

    /// Source directory
    pub const SRC_DIR: &str = "src";
}

/// Configuration paths within project
pub mod config {
    /// Base configs directory
    pub const DIR: &str = "configs";

    /// Node configs base directory
    pub const NODES_DIR: &str = "configs/nodes";

    /// Framework node configs (@mecha10 scope)
    pub const NODES_MECHA10_DIR: &str = "configs/nodes/@mecha10";

    /// Local node configs (@local scope)
    pub const NODES_LOCAL_DIR: &str = "configs/nodes/@local";

    /// Simulation configs directory
    pub const SIMULATION_DIR: &str = "configs/simulation";

    /// Simulation config file
    pub const SIMULATION_CONFIG: &str = "configs/simulation/config.json";

    /// Get config path for a framework node
    pub fn framework_node(node_name: &str) -> String {
        format!("configs/nodes/@mecha10/{}/config.json", node_name)
    }

    /// Get config path for a local node
    pub fn local_node(node_name: &str) -> String {
        format!("configs/nodes/@local/{}/config.json", node_name)
    }

    /// Get config path for a project node (plain name)
    pub fn project_node(node_name: &str) -> String {
        format!("configs/nodes/{}/config.json", node_name)
    }
}

/// Docker-related paths within project
pub mod docker {
    /// Docker directory
    pub const DIR: &str = "docker";

    /// Main docker-compose file
    pub const COMPOSE_FILE: &str = "docker/docker-compose.yml";

    /// Remote nodes docker-compose file
    pub const COMPOSE_REMOTE_FILE: &str = "docker/docker-compose.remote.yml";

    /// Remote nodes Dockerfile
    pub const DOCKERFILE_REMOTE: &str = "docker/Dockerfile.remote";
}

/// Environment files
pub mod env {
    /// Environment example file
    pub const EXAMPLE: &str = ".env.example";

    /// Environment file
    pub const FILE: &str = ".env";
}

/// Meta files (README, gitignore, etc.)
pub mod meta {
    /// README file
    pub const README: &str = "README.md";

    /// Git ignore file
    pub const GITIGNORE: &str = ".gitignore";

    /// Package.json for Node.js tooling
    pub const PACKAGE_JSON: &str = "package.json";

    /// Python requirements
    pub const REQUIREMENTS_TXT: &str = "requirements.txt";

    /// Lint config
    pub const LS_LINT_CONFIG: &str = ".ls-lint.yml";
}

/// Rust project files
pub mod rust {
    /// Cargo workspace manifest
    pub const CARGO_TOML: &str = "Cargo.toml";

    /// Cargo lock file
    pub const CARGO_LOCK: &str = "Cargo.lock";

    /// Main entry point
    pub const MAIN_RS: &str = "src/main.rs";

    /// Library entry point
    pub const LIB_RS: &str = "src/lib.rs";

    /// Build script
    pub const BUILD_RS: &str = "build.rs";

    /// Rustfmt config
    pub const RUSTFMT_TOML: &str = "rustfmt.toml";

    /// Cargo config directory
    pub const CARGO_CONFIG_DIR: &str = ".cargo";

    /// Cargo config file
    pub const CARGO_CONFIG: &str = ".cargo/config.toml";
}

/// Model files within a model directory
pub mod model {
    /// ONNX model file
    pub const ONNX_FILE: &str = "model.onnx";

    /// Labels file
    pub const LABELS_FILE: &str = "labels.txt";

    /// Model config file
    pub const CONFIG_FILE: &str = "config.json";
}

// =============================================================================
// User Home Paths - Paths in ~/.mecha10
// =============================================================================

/// User-level paths in home directory
pub mod user {
    use std::path::PathBuf;

    /// Base mecha10 directory in user home
    pub const MECHA10_DIR: &str = ".mecha10";

    /// Credentials file
    pub const CREDENTIALS_FILE: &str = ".mecha10/credentials.json";

    /// Templates cache directory
    pub const TEMPLATES_DIR: &str = ".mecha10/templates";

    /// Simulation assets cache directory
    pub const SIMULATION_DIR: &str = ".mecha10/simulation";

    /// Current simulation assets symlink
    pub const SIMULATION_CURRENT: &str = ".mecha10/simulation/current";

    /// Simulation version file
    pub const SIMULATION_VERSION: &str = ".mecha10/simulation/version";

    /// Binary installation directory
    pub const BIN_DIR: &str = ".mecha10/bin";

    /// Get the base mecha10 directory path
    pub fn mecha10_dir() -> PathBuf {
        dirs::home_dir()
            .unwrap_or_else(|| PathBuf::from("."))
            .join(MECHA10_DIR)
    }

    /// Get the credentials file path
    pub fn credentials_file() -> PathBuf {
        dirs::home_dir()
            .unwrap_or_else(|| PathBuf::from("."))
            .join(CREDENTIALS_FILE)
    }

    /// Get the templates cache directory
    pub fn templates_dir() -> PathBuf {
        mecha10_dir().join("templates")
    }

    /// Get the simulation assets directory
    pub fn simulation_dir() -> PathBuf {
        mecha10_dir().join("simulation")
    }

    /// Get the current simulation assets path
    pub fn simulation_current() -> PathBuf {
        mecha10_dir().join("simulation/current")
    }

    /// Get the binary directory
    pub fn bin_dir() -> PathBuf {
        mecha10_dir().join("bin")
    }

    /// Get path to a binary in the mecha10 bin directory
    pub fn bin(name: &str) -> PathBuf {
        bin_dir().join(name)
    }

    /// Get path to a binary in cargo bin directory
    pub fn cargo_bin(name: &str) -> PathBuf {
        dirs::home_dir()
            .unwrap_or_else(|| PathBuf::from("."))
            .join(".cargo/bin")
            .join(name)
    }

    /// Get path to a binary in local bin directory
    pub fn local_bin(name: &str) -> PathBuf {
        dirs::home_dir()
            .unwrap_or_else(|| PathBuf::from("."))
            .join(".local/bin")
            .join(name)
    }
}

// =============================================================================
// Docker Container Paths - Paths used inside containers
// =============================================================================

/// Paths used inside Docker containers
pub mod container {
    /// Project mount point in container
    pub const PROJECT_ROOT: &str = "/project";

    /// Framework mount point in container
    pub const FRAMEWORK_ROOT: &str = "/mecha10";

    /// App directory (for mecha10-remote)
    pub const APP_ROOT: &str = "/app";

    /// Config file in mecha10-remote container
    pub const REMOTE_CONFIG: &str = "/app/mecha10.json";

    /// Framework Godot project path (new structure)
    pub const FRAMEWORK_GODOT_PROJECT: &str = "/mecha10/packages/simulation/godot-project";

    /// Framework Godot project path (legacy)
    pub const FRAMEWORK_GODOT_PROJECT_LEGACY: &str = "/mecha10/godot-project";

    /// Get project-relative path inside container
    pub fn project_path(relative: &str) -> String {
        format!("{}/{}", PROJECT_ROOT, relative)
    }

    /// Get framework-relative path inside container
    pub fn framework_path(relative: &str) -> String {
        format!("{}/{}", FRAMEWORK_ROOT, relative)
    }
}

// =============================================================================
// Framework Paths - Paths within mecha10 framework source
// =============================================================================

/// Paths within the mecha10 framework source
pub mod framework {
    /// Packages directory
    pub const PACKAGES_DIR: &str = "packages";

    /// Nodes package directory
    pub const NODES_DIR: &str = "packages/nodes";

    /// Drivers package directory
    pub const DRIVERS_DIR: &str = "packages/drivers";

    /// Services package directory
    pub const SERVICES_DIR: &str = "packages/services";

    /// Simulation package directory
    pub const SIMULATION_DIR: &str = "packages/simulation";

    /// Simulation Godot project
    pub const SIMULATION_GODOT_DIR: &str = "packages/simulation/godot-project";

    /// Simulation models directory
    pub const SIMULATION_MODELS_DIR: &str = "packages/simulation/models";

    /// Simulation environments directory
    pub const SIMULATION_ENVIRONMENTS_DIR: &str = "packages/simulation/environments";

    /// Robot tasks environments directory (for environment matching)
    pub const ROBOT_TASKS_DIR: &str = "packages/simulation/environments/robot-tasks";

    /// Robot tasks catalog file
    pub const ROBOT_TASKS_CATALOG: &str = "packages/simulation/environments/robot-tasks/catalog.json";

    /// Python taskrunner package
    pub const TASKRUNNER_DIR: &str = "packages/taskrunner";

    /// Release binary
    pub const RELEASE_BINARY: &str = "target/release/mecha10";

    /// Debug binary
    pub const DEBUG_BINARY: &str = "target/debug/mecha10";

    /// Node runner release binary
    pub const NODE_RUNNER_RELEASE: &str = "target/release/mecha10-node-runner";

    /// Node runner debug binary
    pub const NODE_RUNNER_DEBUG: &str = "target/debug/mecha10-node-runner";

    /// Get node package path
    pub fn node_package(node_name: &str) -> String {
        format!("packages/nodes/{}", node_name)
    }

    /// Get node config path within framework
    pub fn node_config(node_name: &str) -> String {
        format!("packages/nodes/{}/configs/config.json", node_name)
    }

    /// Get node lib.rs path within framework
    pub fn node_lib_rs(node_name: &str) -> String {
        format!("packages/nodes/{}/src/lib.rs", node_name)
    }
}

// =============================================================================
// External URLs
// =============================================================================

/// External service URLs
pub mod urls {
    /// GitHub repository for user-tools (templates, assets)
    pub const USER_TOOLS_REPO: &str = "mecha-industries/user-tools";

    /// Remote image manifest URL
    pub const REMOTE_MANIFEST: &str =
        "https://raw.githubusercontent.com/laboratory-one/user-tools/main/mecha10-remote/manifest.json";

    /// Default authentication URL
    pub const AUTH_URL: &str = "https://mecha.industries/api/auth";
}

// =============================================================================
// Helper Functions
// =============================================================================

/// Build a target output path
pub fn target_path(profile: &str, binary: &str) -> String {
    format!("target/{}/{}", profile, binary)
}

/// Build a target output path with optional target triple
pub fn target_path_with_triple(target: Option<&str>, profile: &str) -> String {
    match target {
        Some(t) => format!("target/{}/{}", t, profile),
        None => format!("target/{}", profile),
    }
}

/// Get the project root by finding mecha10.json
pub fn find_project_root(start: &Path) -> Option<PathBuf> {
    let mut current = start.to_path_buf();
    loop {
        if current.join(PROJECT_CONFIG).exists() {
            return Some(current);
        }
        if !current.pop() {
            return None;
        }
    }
}

/// Check if a directory is a mecha10 project
pub fn is_project_dir(dir: &Path) -> bool {
    dir.join(PROJECT_CONFIG).exists()
}

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

    #[test]
    fn test_config_paths() {
        assert_eq!(
            config::framework_node("object-detector"),
            "configs/nodes/@mecha10/object-detector/config.json"
        );
        assert_eq!(
            config::local_node("my-node"),
            "configs/nodes/@local/my-node/config.json"
        );
        assert_eq!(
            config::project_node("camera"),
            "configs/nodes/camera/config.json"
        );
    }

    #[test]
    fn test_target_path() {
        assert_eq!(target_path("release", "my-node"), "target/release/my-node");
        assert_eq!(
            target_path_with_triple(Some("aarch64-unknown-linux-gnu"), "release"),
            "target/aarch64-unknown-linux-gnu/release"
        );
        assert_eq!(target_path_with_triple(None, "debug"), "target/debug");
    }

    #[test]
    fn test_container_paths() {
        assert_eq!(
            container::project_path("configs/test.json"),
            "/project/configs/test.json"
        );
        assert_eq!(
            container::framework_path("packages/core"),
            "/mecha10/packages/core"
        );
    }
}
