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

#include <filesystem>

namespace dropshell {


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


config::config() {
}
config::~config() {
}

bool config::load_config() {
    std::string config_path = localfile::dropshell_env();
    if (config_path.empty() || !std::filesystem::exists(config_path))
        return false;

    envmanager config_env(config_path);
    if (!config_env.load())
        return false;

    std::string directories = config_env.get_variable_substituted("local.config.directories");
    if (directories.empty())
        return false;   

    // Split the directories string into a vector of strings
    mLocalConfigPaths = string2multi(directories);

    mLocalBackupPath = config_env.get_variable_substituted("local.backup.directory");

    // legacy config file conversion
    if (mLocalBackupPath.empty() && mLocalConfigPaths.size()>0)
        mLocalBackupPath = mLocalConfigPaths[0] + "/backups";

    //std::cout << "Local config path: " << mLocalConfigPath << std::endl;
    return true;
}

void config::save_config()
{
    if (mLocalConfigPaths.empty())
    {
        std::cerr << "Warning: Unable to save configuration file, as DropShell has not been initialised."<< std::endl;
        std::cerr << "Please run 'dropshell init <path>' to initialise DropShell." << std::endl;
        return;
    }

    std::string parent_path = dropshell::get_parent(localfile::dropshell_env());
    std::filesystem::create_directories(parent_path);

    std::string config_path = localfile::dropshell_env();
    envmanager config_env(config_path);

    config_env.set_variable("local.config.directories", multi2string(mLocalConfigPaths));
    config_env.set_variable("local.backup.directory", mLocalBackupPath);
    config_env.save();
}

bool config::is_config_set() const
{   
    return !mLocalConfigPaths.empty() && !mLocalBackupPath.empty();
}


const std::vector<std::string> & config::get_local_config_directories() const
{
    return mLocalConfigPaths;
}

bool config::add_local_config_directory(const std::string &path)
{
    if (path.empty())
        return false;

    // Convert to canonical path, using std::filesystem
    std::filesystem::path abs_path = std::filesystem::canonical(path);
    
    // The directory must exist
    if (!std::filesystem::exists(abs_path)) {
        std::cerr << "Error: The local config directory does not exist: " << abs_path.string() << std::endl;
        return false;
    }

    // Add to config paths if not already there
    for (auto &p : mLocalConfigPaths)
    { // robustly compare the two paths.
        if (p == abs_path.string())
        {
            std::cerr << "Warning: The local config directory is already registered: " << abs_path.string() << std::endl;
            std::cerr << "No changes made to the DropShell configuration." << std::endl;
            return false;
        }
    }
    mLocalConfigPaths.push_back(abs_path.string());

    if (mLocalBackupPath.empty())
            mLocalBackupPath = abs_path.string() + "/backups";

    return true;
}

const std::string &config::get_local_backup_path() const
{
    return mLocalBackupPath;
}

} // namespace dropshell 