#include "poi_fixture.h"
#include <maps/wikimap/mapspro/services/tasks_sprav/src/export_poi_worker/json2ymapsdf.h>
#include <maps/wikimap/mapspro/services/tasks_sprav/src/export_poi_worker/revision2json.h>

#include <yandex/maps/wiki/revision/branch_manager.h>
#include <yandex/maps/wiki/revision/commit_manager.h>
#include <yandex/maps/wiki/revision/revisionsgateway.h>
#include <yandex/maps/wiki/revisionapi/revisionapi.h>
#include <yandex/maps/wiki/unittest/localdb.h>
#include <yandex/maps/wiki/unittest/config.h>
#include <maps/libs/log8/include/log8.h>


#include <util/system/fs.h>
#include <library/cpp/resource/resource.h>
#include <library/cpp/testing/common/env.h>

#include <boost/test/test_tools.hpp>
#include <boost/format.hpp>

#include <filesystem>

namespace fs = std::filesystem;
namespace rev = maps::wiki::revision;

using namespace maps;
using namespace maps::wiki;
using namespace maps::wiki::poi;

namespace maps {
namespace wiki {
namespace poi {
namespace tests {

namespace {
const std::string TEST_DATA_PATH = SRC_("tds.json");
const std::string TEST_DIR_PATH = (GetOutputPath() / "deleteme").c_str();
const std::string TEST_YMAPSDF_XML_PATH =
    BinaryPath("maps/wikimap/mapspro/tools/ymapsdf-conversion"
               "/json2ymapsdf/cfg/packages/test/export_poi/json2ymapsdf.xml");

const std::string JSON2YMAPSDF_PATH =
    BinaryPath("maps/wikimap/mapspro/tools/"
               "ymapsdf-conversion/json2ymapsdf/bin/json2ymapsdf");

const std::string TEST_CONFIG_XML_TEMPLATE = R"(
    <services>
        <tasks>
            <export conn-str="%1%">
                <mds host="storage-int.mdst.yandex.net"
                     namespace-name="mpro-dataset"
                     auth-header="Basic bXByby1kYXRhc2V0OjhmZTU5ZGNjMzUzMzc4ODdkNzIxOWE4M2IwNWI4ZWRk"/>
            </export>
        </tasks>
    </services>)";
}

SetLogLevelFixture::SetLogLevelFixture()
{
    log8::setLevel(log8::Level::FATAL);
}

PoiFixture::PoiFixture()
        : SetLogLevelFixture()
        , unittest::MapsproDbFixture()
        , configFileHolder_(host(), port(), dbname(), user(), password(),
            str(boost::format(TEST_CONFIG_XML_TEMPLATE) % connectionString()))
        , configXml_(configFileHolder_.filepath())
        , startTime_(fillTds())
        , cfg_(configXml_,
               "trunk",
               chrono::TimePoint::clock::now(),
               TEST_DIR_PATH,
               NResource::Find(rubrics::RUBRICS_MAPPING_CONFIG_RESOURCE_ID),
               TEST_YMAPSDF_XML_PATH)
{
    fs::remove_all(TEST_DIR_PATH);
    fs::create_directories(TEST_DIR_PATH);
    auto txn = pool().masterWriteableTransaction();
    rev::BranchManager(*txn).createApproved(USER_ID, {});
    rev::CommitManager(*txn).approveAll(
        rev::RevisionsGateway(*txn).headCommitId());
    txn->commit();
}

std::time_t
PoiFixture::startTime() const { return startTime_; }

const Config&
PoiFixture::config() const { return cfg_; }

void
PoiFixture::fillYMapsDF()
{
    BuildDirGuard bdg;
    revision2json(cfg_, json2ymapsdfPath());
    json2ymapsdf(cfg_, Json2YMapsDfMode::Upload, json2ymapsdfPath());
}

bool
PoiFixture::doesSchemaExist(const std::string& schema)
{
    auto txn = pool().masterReadOnlyTransaction();
    return txn->exec("SELECT COUNT(*) FROM pg_catalog.pg_namespace WHERE "
                     "nspname = '" + schema + "'")
               .front()
               .front()
               .as<size_t>() != 0;
}

std::time_t
PoiFixture::fillTds()
{
    auto result = std::time(nullptr);
    {   // import data from json
        std::ifstream json(TEST_DATA_PATH);
        BOOST_REQUIRE_MESSAGE(json, "Could not open file " << TEST_DATA_PATH);

        revisionapi::RevisionAPI revision(pool());
        revision.importData(USER_ID, revisionapi::IdMode::StartFromJsonId, json);
    }
    auto txn = pool().masterWriteableTransaction();
    txn->exec("ALTER SEQUENCE revision.object_id_seq RESTART WITH 13787134532");
    txn->commit();
    return result;
}

const std::string&
PoiFixture::json2ymapsdfPath() const
{
    return JSON2YMAPSDF_PATH;
}

BuildDirGuard::BuildDirGuard()
    : originalDir_(NFs::CurrentWorkingDirectory())
{
    NFs::SetCurrentWorkingDirectory(BuildRoot());
}

BuildDirGuard::~BuildDirGuard()
{
    NFs::SetCurrentWorkingDirectory(originalDir_);
}

}//tests
}//poi
}//wiki
}//maps




