use std::{env, fs, path::PathBuf, process::Command};

use dsx_common::builder::{self, BuildContext};
use reqwest::Url;

pub mod new;
pub mod repo;
pub mod templates;

fn main() {
    // Very small CLI – only three sub‑commands.
    let args: Vec<String> = env::args().collect();
    if args.len() < 2 {
        eprintln!("Usage: dsx-build <new|build|package> [options]");
        std::process::exit(1);
    }
    match args[1].as_str() {
        "new" => new::new_project(&args[2..]),
        "build" => {
            if let Some(dir) = find_project_root() {
                let ctx = BuildContext {
                    project_dir: dir.clone(),
                    build_dir: dir.join("build"),
                    artifact_dir: dir.join("artifacts"),
                };

                builder::build_project(ctx).expect("Build failed!");
            } else {
                eprintln!("No Dsx.toml found");
                std::process::exit(1);
            }
        }
        "clean" => {
            if let Some(dir) = find_project_root() {
                fs::remove_dir_all(dir.join("build"))
                    .expect("failed to remove build dir");
                println!("Build directory cleaned...");
                fs::remove_dir_all(dir.join("artifacts"))
                    .expect("failed to remove artifacts dir");
                println!("Artifacts directory cleaned...");
            } else {
                eprintln!("No Dsx.toml found");
                std::process::exit(1);
            }
        }
        "run" => {
            if let Some(dir) = find_project_root() {
                let ctx = BuildContext {
                    project_dir: dir.clone(),
                    build_dir: dir.join("build"),
                    artifact_dir: dir.join("artifacts"),
                };

                builder::build_project(ctx).expect("Run failed!");

                // start process and call emulator
                let mut child = Command::new("dsa")
                    .arg("--cli")
                    .arg("--bin")
                    .arg(dir.join("./artifacts/out.dsb"))
                    .spawn()
                    .expect("Failed to start emulator");

                // wait for emulator to finish
                child.wait().expect("Failed to wait for emulator");
            } else {
                eprintln!("No Dsx.toml found");
                std::process::exit(1);
            }
        }
        "clone" => {
            let url: Url = Url::parse(&args[2]).unwrap();
            let name = url.path_segments().unwrap().next_back().unwrap();
            let repo = env::current_dir().unwrap().join(name);

            fs::create_dir_all(&repo).unwrap();
            repo::clone(&repo, &url).expect("Failed to clone repository");
        }
        "push" => {
            if let Some(dir) = find_project_root() {
                repo::push(&dir).expect("Failed to push repository");
            } else {
                eprintln!("No Dsx.toml found");
                std::process::exit(1);
            }
        }
        "pull" => {
            if let Some(dir) = find_project_root() {
                repo::pull(&dir).expect("Failed to pull repository");
            } else {
                eprintln!("No Dsx.toml found");
                std::process::exit(1);
            }
        }
        "package" => todo!("Package manager stub – not implemented yet."),
        _ => {
            eprintln!("Unknown command: {}", args[1]);
            std::process::exit(1);
        }
    }
}

fn find_project_root() -> Option<PathBuf> {
    // check if current dir has Dsx.toml otherwise check parent dir recursively
    let mut cwd = env::current_dir().unwrap();
    loop {
        let dsx_toml = cwd.join("Dsx.toml");
        if dsx_toml.exists() {
            return Some(cwd);
        }

        if let Some(parent) = cwd.parent() {
            cwd = parent.to_path_buf();
        } else {
            break;
        }
    }

    None
}
