#include <iostream>
#include <filesystem>
#include <unistd.h>

#include "argparse.hpp"
#include "generator.hpp"
#include "version.hpp"


std::string get_arch()
{
    // determine the architecture of the system
    std::string arch;
#ifdef __aarch64__
    arch = "arm64";
#elif __x86_64__
    arch = "amd64";
#endif
    return arch;
}

int update()
{
    // determine path to this executable
    std::filesystem::path exepath = std::filesystem::canonical("/proc/self/exe");
    std::filesystem::path parent_path = exepath.parent_path();
    std::string project_name = exepath.filename().string();

    // determine the architecture of the system
    std::string arch = get_arch();

    std::string url = "https://gitea.jde.nz/public/"+project_name+"/releases/download/latest/"+project_name+"." + arch;

    // download new version, preserve permissions and ownership
    std::string bash_script;
    bash_script += "docker run --rm -v "+parent_path.string()+":/target";
    bash_script += " gitea.jde.nz/public/debian-curl:latest";
    bash_script += " sh -c \"";
    bash_script += " curl -fsSL " + url + " -o /target/"+project_name+"_temp &&";
    bash_script += " chmod --reference=/target/"+project_name+" /target/"+project_name+"_temp &&";
    bash_script += " chown --reference=/target/"+project_name+" /target/"+project_name+"_temp &&";
    bash_script += " mv /target/"+project_name+"_temp /target/"+project_name;
    bash_script += "\"";

    std::cout << "Updating " << exepath << " to the latest " << arch << " version." << std::endl;

    // std::cout << "bash_script: " << std::endl
    //           << bash_script << std::endl;

    // run the bash script
    execlp("bash", "bash", "-c", bash_script.c_str(), (char *)nullptr);
    std::cerr << "Failed to execute command." << std::endl;
    return -1;
}



int main(int argc, char* argv[]) {
    try {
        Args args = parse_args(argc, argv);
        
        // Handle version request (output only version)
        if (args.version) {
            std::cout << VERSION << std::endl;
            return 0;
        }
        
        // Handle update request
        if (args.update) {
            std::cout << "Dehydrate version " << VERSION << std::endl;
            return update();
        }
        
        // Show version for normal operations (unless silent)
        if (!args.silent) {
            std::cout << "Dehydrate version " << VERSION << std::endl;
        }
        
        std::filesystem::path src(args.source);
        if (!std::filesystem::exists(src)) {
            std::cerr << "Source does not exist: " << args.source << std::endl;
            return 1;
        }
        if (std::filesystem::is_regular_file(src)) {
            generate_file_code(args.source, args.dest, args.silent);
        } else if (std::filesystem::is_directory(src)) {
            generate_folder_code(args.source, args.dest, args.silent);
        } else {
            std::cerr << "Source is neither a file nor a directory: " << args.source << std::endl;
            return 1;
        }
    } catch (const std::exception& ex) {
        std::cerr << ex.what() << std::endl;
        return 1;
    }
    return 0;
} 