#include "temp_directory.hpp"
#include "logger.hpp"

#include <filesystem>
#include <string>
#include <random>
#include <chrono>
#include <stdexcept>
#include <iostream> // For error reporting in destructor

namespace simple_object_storage {

TempDirectory::TempDirectory(const std::string& prefix) {
    auto temp_dir_base = std::filesystem::temp_directory_path();
    std::mt19937_64 rng(std::chrono::high_resolution_clock::now().time_since_epoch().count());
    std::uniform_int_distribution<uint64_t> dist;

    int retries = 5; // Avoid infinite loop in edge cases
    while (retries-- > 0) {
        std::string random_suffix = std::to_string(dist(rng));
        path_ = temp_dir_base / (prefix + random_suffix);
        if (!std::filesystem::exists(path_)) {
                break; // Found a unique path
        }
    }

    if (std::filesystem::exists(path_)) {
        throw std::runtime_error("Failed to find unique temporary directory path after multiple retries.");
    }

    try {
        if (!std::filesystem::create_directory(path_)) {
            throw std::runtime_error("Failed to create temporary directory: " + path_.string());
        }
    } catch (const std::filesystem::filesystem_error& e) {
        throw std::runtime_error("Filesystem error creating temporary directory: " + path_.string() + " - " + e.what());
    }
}

TempDirectory::~TempDirectory() {
    try {
        if (std::filesystem::exists(path_)) {
            std::error_code ec; // Use error code to avoid exceptions in destructor
            std::filesystem::remove_all(path_, ec);
            if (ec) {
                    LOG_ERROR("Error removing temporary directory {}: {}", path_.string(), ec.message());
            }
        }
    } catch (const std::exception& e) { // Catch potential exceptions from exists() though unlikely
            LOG_ERROR("Error during temporary directory cleanup for {}: {}", path_.string(), e.what());
    } catch (...) {
            LOG_ERROR("Unknown error during temporary directory cleanup for {}", path_.string());
    }
}

const std::filesystem::path& TempDirectory::path() const {
    return path_;
}

std::string TempDirectory::string() const {
    return path_.string();
}

} // namespace simple_object_storage 