#include "utils/directories.hpp"
#include <iostream>
#include <fstream>
#include "config.hpp"
#include "utils/utils.hpp"
#include "utils/json.hpp"
#include <filesystem>

namespace dropshell {


config & gConfig() {
    static config *globalConfig = new config();
    return *globalConfig;
}


config::config() : mIsConfigSet(false) {
}

config::~config() {
}

bool config::load_config() { // load json config file.
    std::string config_path = localfile::dropshell_json();
    if (config_path.empty() || !std::filesystem::exists(config_path))
        return false;

    std::ifstream config_file(config_path);
    if (!config_file.is_open())
        return false;

    try {
        mConfig = nlohmann::json::parse(config_file);
    }
    catch (nlohmann::json::parse_error& ex)
    {
        std::cerr << "Error: Failed to parse config file: " << ex.what() << std::endl;
        return false;
    }

    mIsConfigSet = true;
    return true;
}

bool config::save_config(bool create_aux_directories)
{
    std::string config_path = localfile::dropshell_json();
    if (config_path.empty())
        return false;

    std::filesystem::create_directories(get_parent(config_path));

    std::ofstream config_file(config_path);
    if (!config_file.is_open())
        return false;

    if (!mIsConfigSet)
    {
        std::string homedir = localpath::current_user_home();
        std::string dropshell_base = homedir + "/.dropshell";
        mConfig["tempfiles"] = dropshell_base + "/tmp";
        mConfig["backups"] = dropshell_base + "/backups";
        mConfig["template_cache"] = dropshell_base + "/template_cache";
        mConfig["template_registry_URLs"] = {
            "https://templates.dropshell.app"
        };
        mConfig["template_local_paths"] = {
            dropshell_base + "/local_templates"
        };
        mConfig["server_definition_paths"] = {
            dropshell_base + "/servers"
        };
        mConfig["template_upload_registry_url"] = "https://templates.dropshell.app"; 
        mConfig["template_upload_registry_token"] = "SECRETTOKEN";
    }   

    config_file << mConfig.dump(4);
    config_file.close();

    if (create_aux_directories) {
        std::vector<std::filesystem::path> paths = {
            get_local_template_cache_path(),
            get_local_backup_path(),
            get_local_tempfiles_path()
        };
        for (auto & p : get_local_server_definition_paths()) 
            paths.push_back(p);

        for (auto & p : paths)
            if (!std::filesystem::exists(p))
            {
                std::cout << "Creating directory: " << p << std::endl;
                std::filesystem::create_directories(p);
            }
    }

    return true;
}
  

bool config::is_config_set() const
{   
    return mIsConfigSet;
}

std::string config::get_local_tempfiles_path() {
    return mConfig["tempfiles"];
}

std::string config::get_local_backup_path() {
    return mConfig["backups"];
}

std::string config::get_local_template_cache_path() {
    return mConfig["template_cache"];
}

std::vector<std::string> config::get_template_registry_urls() {
    nlohmann::json template_registry_urls = mConfig["template_registry_URLs"];
    std::vector<std::string> urls;
    for (auto &url : template_registry_urls) {
        urls.push_back(url);
    }
    return urls;
}

std::vector<std::string> config::get_template_local_paths()
{
    nlohmann::json template_local_paths = mConfig["template_local_paths"];
    std::vector<std::string> paths;
    for (auto &path : template_local_paths) {
        if (path.is_string() && !path.empty())
            paths.push_back(path);
    }
    return paths;
}

std::vector<std::string> config::get_local_server_definition_paths() {
    nlohmann::json server_definition_paths = mConfig["server_definition_paths"];

    std::vector<std::string> paths;
    for (auto &path : server_definition_paths) {
        if (path.is_string() && !path.empty())
        {
            paths.push_back(path);
        }
        else
            std::cerr << "Warning: Invalid server definition path: " << path << std::endl;
    }
    return paths;
}

std::string config::get_template_upload_registry_url() {
    return mConfig["template_upload_registry_url"];
}

std::string config::get_template_upload_registry_token() {
    return mConfig["template_upload_registry_token"];
}

} // namespace dropshell 