#pragma once

#include "local_server.h"

#include <maps/libs/common/include/temporary_dir.h>
#include <maps/libs/local_mongo/include/mongo_server.h>
#include <maps/libs/mongo/include/init.h>

#include <maps/libs/log8/include/log8.h>

#include <boost/filesystem.hpp>
#include <boost/format.hpp>

#include <library/cpp/testing/common/env.h>

namespace maps::mrc::unittest {

const std::string TMPFS_DIR_NAME = "/dev/shm";

class UniqueTempGrinderConfig {
public:
    UniqueTempGrinderConfig(const std::string& baseDir,
            std::uint16_t mongoPort, const std::string& mongoDbName)
        : path_(boost::filesystem::path(baseDir) / boost::filesystem::unique_path("grinder.conf.%%%%"))
    {
        std::ofstream f(path_.string());
        f << (boost::format(R"(
{
  "mongo": {
      "uri": "mongodb://localhost:%1%/%2%"
  }
}
                )") % mongoPort % mongoDbName);
    }

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

    ~UniqueTempGrinderConfig()
    {
        boost::system::error_code err;
        boost::filesystem::remove_all(path_, err);
        if (err) {
            WARN() << "Failed to delete temporary directory " << path_
                   << " - " << err.message();
        }
    }

private:
    boost::filesystem::path path_;
};

class MongocxxFixture
{
public:
    MongocxxFixture()
    {
        mongo::init();
    }
};

class GrinderFixture : MongocxxFixture
{
public:
    GrinderFixture() :
        grinderConfigHolder_(GetWorkPath(), mongoServer_.port(), "test_db")
    {
        WaitForTestServer waitForMongo(mongoServer_.port());
    }

    std::string grinderConfigPath() const { return grinderConfigHolder_.path(); }

private:
    local_mongo::MongoServer mongoServer_;
    UniqueTempGrinderConfig grinderConfigHolder_;
};

} // namespace maps::mrc::unittest
