#include "envmanager.hpp"
#include "utils/utils.hpp"
#include <fstream>
#include <sstream>
#include <algorithm>
#include <cctype>
#include <regex>
#include <cstdlib> // For std::getenv

namespace dropshell {

envmanager::envmanager(std::string path) : m_path(path) {
}

envmanager::~envmanager() {
}

bool envmanager::load() {
    std::ifstream file(m_path);
    if (!file.is_open()) {
        return false;
    }

    m_variables.clear();
    std::string line;
    while (std::getline(file, line)) {
        line=trim(line);
        // Skip empty lines and comments
        if (line.empty() || line[0] == '#') {
            continue;
        }

        size_t pos = line.find('=');
        if (pos != std::string::npos) {
            std::string key = line.substr(0, pos);
            std::string value = line.substr(pos + 1);

            // trim whitespace from the key and value
            m_variables[dequote(trim(key))] = dequote(trim(value));
        }
    }
    file.close();
    return true;
}

void envmanager::save() {
    std::ofstream file(m_path);
    if (!file.is_open()) {
        return;
    }

    for (const auto& pair : m_variables) {
        file << pair.first << "=" << quote(pair.second) << std::endl;
    }
    file.close();
}

std::string envmanager::get_variable(std::string key) const {
    key = dequote(trim(key));
    
    // Use case-insensitive comparison to find the key
    for (const auto& pair : m_variables) {
        if (pair.first == key) {
            return pair.second;
        }
    }
    
    return "";
}

void envmanager::get_all_variables(std::map<std::string, std::string>& variables) const {
    variables = m_variables;
}

std::string envmanager::get_variable_substituted(std::string key) const {
    std::string value = get_variable(key);
    return expand_patterns(value);
}

void envmanager::get_all_variables_substituted(std::map<std::string, std::string>& variables) const {
    variables.clear();
    for (const auto& pair : m_variables) {
        variables[pair.first] = expand_patterns(pair.second);
    }
}

void envmanager::add_variables(std::map<std::string, std::string> variables) {
    for (auto& pair : variables) {
        set_variable(pair.first, pair.second);
    }
}

void envmanager::set_variable(std::string key, std::string value) {
    m_variables[dequote(trim(key))] = dequote(trim(value));
}

void envmanager::clear_variables() {
    m_variables.clear();
}

std::string envmanager::expand_patterns(std::string str) const {
    // Combined regex pattern for both ${var} and $var formats
    std::regex var_pattern("\\$(?:\\{([^}]+)\\}|([a-zA-Z0-9_]+))");
    std::string result = str;
    std::smatch match;
    
    while (std::regex_search(result, match, var_pattern)) {
        // match[1] will contain capture from ${var} format
        // match[2] will contain capture from $var format
        std::string var_name = match[1].matched ? match[1].str() : match[2].str();
        
        // Get value from system environment variables
        const char* env_value = std::getenv(var_name.c_str());
        std::string value = env_value ? env_value : "";
        
        result = result.replace(match.position(), match.length(), value);
    }

    // dequote the result
    return result;
}

} // namespace dropshell
