#include "FileAddressList.hpp"

#include <spdlog/spdlog.h>
#include <filesystem>
#include <fstream>
#include <cstdlib>
#include <algorithm>

namespace tw::app {

namespace {

std::string get_config_dir() {
    // Try XDG_CONFIG_HOME first
    const char* xdg_config_home = std::getenv("XDG_CONFIG_HOME");
    if(xdg_config_home && xdg_config_home[0] != '\0') {
        return std::string(xdg_config_home) + "/towards";
    }

    // Fall back to $HOME/.config/towards
    const char* home = std::getenv("HOME");
    if(home && home[0] != '\0') {
        return std::string(home) + "/.config/towards";
    }

    // Both unset
    return "";
}

} // anonymous namespace

FileAddressList::FileAddressList(const std::string& file_name) {
    std::string config_dir = get_config_dir();

    if(config_dir.empty()) {
        spdlog::debug("XDG_CONFIG_HOME and HOME not set; address lists will not be persisted");
        m_can_save = false;
        return;
    }

    m_path = config_dir + "/" + file_name;
    m_can_save = true;
}

void FileAddressList::load() {
    if(m_path.empty()) {
        return; // No config path available
    }

    std::ifstream file(m_path);
    if(!file.is_open()) {
        // File doesn't exist or can't be read; this is not an error
        return;
    }

    m_entries.clear();
    std::string line;
    while(std::getline(file, line)) {
        // Trim whitespace from the line
        size_t start = line.find_first_not_of(" \t\r\n");
        size_t end = line.find_last_not_of(" \t\r\n");

        if(start != std::string::npos) {
            line = line.substr(start, end - start + 1);
            if(!line.empty()) {
                m_entries.push_back(line);
            }
        }
    }
}

void FileAddressList::save() const {
    if(!m_can_save || m_path.empty()) {
        return; // Cannot save without config path
    }

    // Create the directory if needed
    std::filesystem::path config_path(m_path);
    std::filesystem::path config_dir = config_path.parent_path();

    try {
        std::filesystem::create_directories(config_dir);
    } catch(const std::filesystem::filesystem_error&) {
        // If we can't create the directory, silently fail to save
        return;
    }

    // Write entries to file
    std::ofstream file(m_path);
    if(!file.is_open()) {
        return; // Can't open file for writing; silently fail
    }

    for(const auto& entry : m_entries) {
        file << entry << "\n";
    }
}

void FileAddressList::remove(const std::string& entry) {
    auto it = std::find(m_entries.begin(), m_entries.end(), entry);
    if(it != m_entries.end()) {
        m_entries.erase(it);
    }
}

const std::vector<std::string>& FileAddressList::entries() const {
    return m_entries;
}

} // namespace tw::app
