//! `rok new <app-name>` — scaffold a new rok/Axum project from a template.

use std::path::Path;

use super::templates::{self, Template};

pub fn run(name: &str, template: Option<&str>) -> anyhow::Result<()> {
    let root = Path::new(name);
    if root.exists() {
        anyhow::bail!("Directory '{name}' already exists.");
    }

    let tmpl = match template {
        Some(t) => Template::from_str(t)?,
        None => templates::prompt_template()?,
    };

    println!(
        "Creating rok application: {name} (template: {})",
        tmpl.label()
    );
    println!();

    std::fs::create_dir_all(root)?;
    tmpl.generate(name, root)?;

    // Best-effort git init — silently skip if git is not installed
    let _ = git_init(root);

    println!();
    println!("Application '{name}' created!");
    println!();
    println!("Next steps:");
    println!("  cd {name}");
    println!("  cp .env.example .env");
    println!("  # Edit .env and set DATABASE_URL");
    println!("  rok serve");

    Ok(())
}

fn git_init(root: &Path) -> anyhow::Result<()> {
    use std::process::Command;

    // Skip when the target is already inside an existing git repo (e.g. a
    // workspace `examples/` directory).  Creating a nested repo would turn it
    // into a git submodule and break the parent repo's tracking.
    let already_in_repo = Command::new("git")
        .args(["rev-parse", "--is-inside-work-tree"])
        .current_dir(root)
        .output()
        .map(|o| o.status.success())
        .unwrap_or(false);
    if already_in_repo {
        return Ok(());
    }

    Command::new("git").arg("init").current_dir(root).output()?;
    Command::new("git")
        .args(["add", "."])
        .current_dir(root)
        .output()?;
    Command::new("git")
        .args(["commit", "-m", "Initial commit (rok new)"])
        .env("GIT_AUTHOR_NAME", "rok")
        .env("GIT_AUTHOR_EMAIL", "rok@localhost")
        .env("GIT_COMMITTER_NAME", "rok")
        .env("GIT_COMMITTER_EMAIL", "rok@localhost")
        .current_dir(root)
        .output()?;
    Ok(())
}
