#include "lifecycle_adapters.h"
#include "../util/logger.h"

#include <algorithm>
#include <array>
#include <chrono>
#include <thread>

namespace dragonx {
namespace daemon {

AsyncLifecycleTaskContext::AsyncLifecycleTaskContext(
    const util::AsyncTaskManager::Token& token,
    const std::atomic<bool>& shuttingDown)
    : token_(token), shuttingDown_(shuttingDown)
{
}

bool AsyncLifecycleTaskContext::cancelled() const
{
    return token_.cancelled();
}

bool AsyncLifecycleTaskContext::shuttingDown() const
{
    return shuttingDown_.load(std::memory_order_relaxed);
}

void AsyncLifecycleTaskContext::sleepForMs(int milliseconds)
{
    std::this_thread::sleep_for(std::chrono::milliseconds(std::max(0, milliseconds)));
}

bool ImmediateLifecycleTaskContext::cancelled() const
{
    return false;
}

bool ImmediateLifecycleTaskContext::shuttingDown() const
{
    return false;
}

void ImmediateLifecycleTaskContext::sleepForMs(int)
{
}

int BlockchainDataCleaner::removeBlockchainData(const std::filesystem::path& dataDir)
{
    namespace fs = std::filesystem;

    static constexpr std::array<const char*, 4> directories = {
        "blocks", "chainstate", "database", "notarizations"
    };
    static constexpr std::array<const char*, 5> files = {
        "peers.dat", "fee_estimates.dat", "banlist.dat", "db.log", ".lock"
    };

    int removed = 0;
    for (const char* directoryName : directories) {
        fs::path path = dataDir / directoryName;
        std::error_code existsError;
        if (!fs::exists(path, existsError)) continue;

        std::error_code removeError;
        auto count = fs::remove_all(path, removeError);
        if (!removeError) {
            removed += static_cast<int>(count);
            DEBUG_LOGF("[DaemonLifecycle] Removed %s (%d entries)\n",
                       directoryName, static_cast<int>(count));
        } else {
            DEBUG_LOGF("[DaemonLifecycle] Failed to remove %s: %s\n",
                       directoryName, removeError.message().c_str());
        }
    }

    for (const char* fileName : files) {
        fs::path path = dataDir / fileName;
        std::error_code removeError;
        if (fs::remove(path, removeError)) {
            ++removed;
            DEBUG_LOGF("[DaemonLifecycle] Removed %s\n", fileName);
        } else if (removeError) {
            DEBUG_LOGF("[DaemonLifecycle] Failed to remove %s: %s\n",
                       fileName, removeError.message().c_str());
        }
    }

    return removed;
}

} // namespace daemon
} // namespace dragonx