use std::env;
use std::fs;
use std::io::stdin;
use std::io::Write;
use std::path::PathBuf;
use std::process;
use std::thread;
use std::time::Duration;
use std::str::FromStr;
use crate::Project;

pub fn switch_project(projects: &mut Vec<Project>){
    for project in projects.clone(){
        if project.active == false{
            println!("{} {}|{}", project.id, project.customer, project.project_name);
        }
    }
    println!("\nnew project selection?\n");
    let mut response = String::new();
    std::io::stdin().read_line(&mut response).unwrap();
    if response.len() > 1{
        let new_id:i32 = response.trim_end().parse().expect("error converting to i32");
        for project in projects{
            if project.id ==  new_id{
                project.active = true;
                println!("project found switching to {} {}", project.customer, project.project_name);
                env::set_var("CURRENT_PROJECT_BOX", project.boxname.clone());
            }
            else if project.id != new_id{
                project.active = false;
            }
            else{
                println!("error unknown project id")
            }
        }
    }
    else{
        println!("error we need user input here dummy!");
    }
    
}

pub fn save_projects(projects: &Vec<Project>, config_path: &PathBuf){
   let mut save_file_path = config_path.clone();
   let mut active_set = false;
    save_file_path.pop();
    save_file_path.push("projects.conf");
    let mut save_file = fs::File::create(save_file_path).expect("error creating save_file");
    save_file.write_all(b"customer:name:notes:files:active:time:box_name\n").expect("error writing first line to file");
    for project in projects{
        let default = format!{"{}:{}:{}:{}:", project.customer, project.project_name, project.notes_folder.display(), project.files_folder.display()};
        let mut _outline = String::new();
        if project.active{
            if active_set == false{
                _outline = format!("{}yes:{}\n", default, project.boxname);
                active_set = true;
            }

        }
        else{
            _outline = format!("{}no:{}\n", default, project.boxname);
        }
        save_file.write_all(_outline.as_bytes()).expect("error writing outline");
    }
}

pub fn new_project(projects: &mut Vec<Project>, project_dir: &PathBuf, notes_dir: &PathBuf, tools_dir: &PathBuf, boxtemplate: &String, config_path: &PathBuf, new_id: i32){
    let mut new_project_dir = project_dir.clone();
    let mut new_note_dir = notes_dir.clone();
    let mut existing_folders = String::new();
    let mut customer_name = String::new();
    let mut project_name = String::new();
    println!("do you have an existing notes and folder structure to copy over?\ny/n");
    std::io::stdin().read_line(&mut existing_folders).unwrap();
    let mut customer_name = customer_name.trim_end().to_owned();
    let mut project_name = project_name.trim_end().to_owned();
    if existing_folders.contains("y") || existing_folders.contains("Y"){
        println!("NOTE THIS WILL OVERWRITE CUSTOMER NAME AND PROJECT NAME WITH THE 2nd TO LAST AND LAST FOLDER NAMES IN THE PATH YOU'RE COPYING RESPECTIVELY");
        let mut files_to_copy = String::new();
        let mut notes_to_copy = String::new();
        println!("path to project folder folder to copy:");
        std::io::stdin().read_line(&mut files_to_copy).unwrap();
        println!("path to notes folder to copy:");
        std::io::stdin().read_line(&mut notes_to_copy).unwrap();
        //to get rid of the new line chars
        files_to_copy.pop();
        notes_to_copy.pop();
        println!("files to copy: {}", files_to_copy);
        println!("notes to copy: {}", notes_to_copy);
        println!("files destination: {}", new_project_dir.display());
        println!("notes destination: {}", new_note_dir.display()); 
        let folder_move_success = process::Command::new("mv")
                                            .arg("-i")
                                            .arg(&files_to_copy)
                                            .arg(new_project_dir.display().to_string())
                                            .status().expect("unable to call the system mv command");
        let note_move_success = process::Command::new("mv")
                                            .arg("-i")
                                            .arg(&notes_to_copy)
                                            .arg(new_note_dir.display().to_string())
                                            .status().expect("unable to call the system mv command");
        if folder_move_success.success(){
            println!("we copied the project folder correctly!!");
        }
        else{
            println!("failed to copy the project folder, try to move it manually!");
        }
        if note_move_success.success(){
            println!("we copied the notes folder correctly!!");
        }
        else{
            println!("failed to copy the notes folder, try to move it manually!");
        }
        // this lovely set of code takes the folder you gave to copy and tries to find the customername and project name based on directory names
        // this solves a case where the entered customer name or project name does not match the files copied
        let copied_files = PathBuf::from(&files_to_copy);
        customer_name = copied_files.file_name().unwrap().to_str().unwrap().to_owned();
        new_project_dir.push(&customer_name);
        new_note_dir.push(&customer_name);
        match fs::read_dir(&new_project_dir){
            Ok(entries) => {
                for entry in entries{
                    match entry {
                        Ok(entry) => {
                            let entry_path = entry.path();
                            if entry_path.is_dir(){
                                if let Some(dir_name) = entry_path.file_name(){
                                    if let Some(dir_name_str) = dir_name.to_str(){
                                        if dir_name_str.contains("pentest"){
                                            project_name = dir_name_str.to_owned();
                                            println!("pentest folder found! assuming projectname...");
                                            new_project_dir.push(&project_name);
                                            new_note_dir.push(&project_name);
                                        }
                                    }
                                }
                            }
                        }
                        Err(e) => eprintln!("error reading entry name: {}", e)
                    }
                }
            }
            Err(e) => eprintln!("Error reading directory entries: {}", e)
        }
        let mut customer_name_response = String::new();
        let mut project_name_response = String::new();
        println!("Customer_name: {}", &customer_name);
        println!("Is this correct?");
        stdin().read_line(&mut customer_name_response).unwrap();
        println!("Project_name: {}", &project_name);
        println!("Is this corrrect?");
        stdin().read_line(&mut project_name_response).unwrap();
        if customer_name_response.contains(|c: char| c == 'n' || c=='N') || project_name_response.contains(|c: char| c == 'n' || c=='N'){
            println!("oops sorry about that, tried to guess based on the second to last and last folder names");
            if customer_name_response.contains(|c: char| c == 'n' || c =='N'){
                let mut name_response = String::new(); 
                println!("what is the correct customer name?");
                stdin().read_line(&mut name_response).unwrap();
                name_response.pop();
                customer_name = name_response.to_owned();
            }
            if project_name_response.contains(|c: char| c == 'n' || c == 'N'){
                let mut project_response = String::new();
                println!("what is the correct project name?");
                stdin().read_line(&mut project_response).unwrap();
                project_response.pop();
                project_name = project_response.to_owned();
            }
        }
    }
    else{
        println!("customer name?");
        std::io::stdin().read_line(&mut customer_name).unwrap();
        println!("project name?");
        std::io::stdin().read_line(&mut project_name).unwrap();
        // to remove newline characters
        customer_name.pop();
        project_name.pop();
        new_project_dir.push(&customer_name);
        new_note_dir.push(&customer_name);
        new_project_dir.push(&project_name);
        new_note_dir.push(&project_name);
        fs::create_dir_all(&new_project_dir).expect("error creating new files folder");
        fs::create_dir_all(&new_note_dir).expect("error creating new notes folder");
    }
    thread::sleep(Duration::from_secs(2));
    let box_name = format!("atarchbox_{}", customer_name);
    let mut box_name_path = new_project_dir.clone();
    box_name_path.push("boxname");
    let mut box_name_file = fs::File::create(box_name_path).expect("Error creating box name file");
    box_name_file.write_all(&box_name.as_bytes()).expect("error writing boxname to box file");
    let pentest_volume = format!("{}:/pentest:rw", new_project_dir.display());
    let toold_volume = format!("{}:/tools:rw", tools_dir.display());
    println!("distrobox create --root --clone {} --volume {} --volume {} --name {}", boxtemplate, toold_volume,  pentest_volume, box_name);
    let distrobox_result = process::Command::new("distrobox")
                                                                .arg("create")
                                                                .arg("--root")
                                                                .arg("--clone")
                                                                .arg(boxtemplate)
                                                                .arg("--volume")
                                                                .arg(&toold_volume)
                                                                .arg("--volume")
                                                                .arg(&pentest_volume)
                                                                .arg("--name")
                                                                .arg(&box_name)
                                                                .status()
                                                                .expect("error getting distrobox status");
    if distrobox_result.success(){
        println!("we made a distrobox oh boy!");
        let distrobox_start_result = process::Command::new("distrobox")
                                                                        .arg("enter")
                                                                        .arg("--root")
                                                                        .arg(&box_name)
                                                                        .arg("--")
                                                                        .arg("sudo")
                                                                        .arg("-s")
                                                                        .arg("ln")
                                                                        .arg("-sf")
                                                                        .arg("/pentest/boxname")
                                                                        .arg("/etc/boxname")
                                                                        .status()
                                                                        .expect("error getting response from distrobox start");
        if distrobox_start_result.success(){
            println!("distrobox was started as well!!!! good job me!");
        }
        else{
            println!("ooof did not start successfully try entering it yoruself");
            println!("distrobox enter --rrot {} -- sudo -s ln -sf /pentest/boxname /etc/boxname", &box_name);
        }
    }
    else{
        println!("ooof distrobox did not work.... try creating it yourself");
        println!("distrobox create --root --clone {} --volume {} --volume {} --name {}", boxtemplate, &toold_volume, &pentest_volume, &box_name);
        println!("distrobox enter --rrot {} -- sudo -s ln -sf /pentest/boxname /etc/boxname", &box_name);
    }
    let new_project = Project{customer: customer_name.trim_end().to_owned(), 
                                    project_name: project_name.trim_end().to_owned(), 
                                    notes_folder: new_note_dir, 
                                    files_folder:new_project_dir, 
                                    active: false,
                                    id: new_id,
                                    boxname: box_name,
                                      };
    projects.push(new_project);
    save_projects(projects, config_path);

}


pub fn remove_project(projects: &mut Vec<Project>, config_path: &PathBuf){
    for project in projects.clone(){
        println!("{} {} {}", project.id, project.customer, project.project_name);
    }
    let mut project_to_remove = String::new();
    println!("project to remove?");
    std::io::stdin().read_line(&mut project_to_remove).unwrap();
    if project_to_remove.len() > 1{
        let mut project_to_keep = Vec::new();
        if project_to_remove.len() > 0{
            let remove_id: i32 = project_to_remove.trim_end().parse().unwrap();
            let mut project_set = false;
            for project in projects.clone(){
                if project.id == remove_id{
                    println!("will remove {} {}", project.customer, project.project_name);
                    project_set = true;
                    let _distrobox_stop_status = process::Command::new("distrobox").arg("stop").arg("--root").arg(&project.boxname).status().expect("error stopping distrobox");
                    let distrobox_rm_status = process::Command::new("distrobox-rm")
                                                                            .arg("--root")
                                                                            .arg("-f")
                                                                            .arg(&project.boxname)
                                                                            .status().expect("error calling distrobox");
                    if distrobox_rm_status.success(){
                        println!("Distrobox Removal Successful!!!");
                    }
                    else{
                        println!("Distrobox Removal Failed, manual removal required!");
                    }
                }
                else {
                    println!("{} {} will be kept", project.customer, project.project_name);
                    project_to_keep.push(project);
                }
            }
            if project_set{
                projects.clear();
                projects.append(&mut project_to_keep);
                save_projects(&projects, config_path);
            }
            else{
                println!("error no prjects found to remove")
            }
            
        }
        else{
            println!("we need user in put here dummy!!");
        }
    }
    else{
        println!("we need input here dummy!");
    }
}

pub fn get_projects(config_path: &PathBuf) -> Vec<Project>{
    let mut mut_config_path = config_path.clone();
    mut_config_path.pop();
    mut_config_path.push("projects.conf");
    let mut projects = Vec::new();
    let projects_string = fs::read_to_string(mut_config_path).expect("error reading projects file");
    let project_lines:Vec<&str> = projects_string.split("\n").collect();
    let mut first = 0;
    let mut already_active = false;
    for line in project_lines{
        first = first + 1;
        if first != 1{
            if line.len() > 1{
                let settings: Vec<&str> = line.split(":").collect();
                let customer = settings[0].to_owned();
                let project = settings[1].to_owned();
                let notes_string = settings[2].to_owned();
                let folder_string = settings[3].to_owned();
                let notes_folder = PathBuf::from_str(&notes_string.trim_end()).expect("error reading notes string");
                let project_folder = PathBuf::from_str(&folder_string.trim_end()).expect("error reading folding sering");
                let mut active = false;
                let boxname = settings[5].to_owned();
                if settings[4] == "yes"{
                    if already_active == false{
                        env::set_var("CURRENT_PROJECT_BOX", boxname.clone());
                        already_active = true;
                        active = true;
                    }
                }
                let new_project = Project{customer: customer, project_name: project, files_folder: project_folder, notes_folder: notes_folder, active: active, id: first, boxname: boxname};
                println!("{} {} LOADED!", &new_project.customer, &new_project.project_name);
                projects.push(new_project);
            }
        }
    }
    return projects
}