#include <maps/wikimap/mapspro/services/mrc/tools/house_numbers_tools/collect_house_numbers/merge_classification_operation/tools.h>

#include <library/cpp/testing/common/env.h>
#include <library/cpp/testing/gtest/gtest.h>
#include <maps/libs/common/include/file_utils.h>
#include <maps/libs/json/include/prettify.h>
#include <maps/libs/log8/include/log8.h>
#include <maps/wikimap/mapspro/services/mrc/libs/common/include/opencv.h>
#include <maps/libs/geolib/include/vector.h>
#include <yandex/maps/mrc/unittest/local_server.h>
#include <yandex/maps/mrc/unittest/unittest_config.h>

namespace maps::mrc::tools::test {
namespace {

const auto IMAGE = common::getTestImage<std::string>();

const auto DATA_DIR = ArcadiaSourceRoot() + "/maps/wikimap/mapspro/services/"
                                            "mrc/tools/house_numbers_tools/"
                                            "collect_house_numbers/"
                                            "merge_classification_operation/"
                                            "tests";

const auto INPUT_JSON
    = maps::common::readFileToString(DATA_DIR + "/input.json");

const auto OUTPUT_JSON
    = maps::common::readFileToString(DATA_DIR + "/output.json");

const std::string URLS[]
    = {"http://storage.mds.yandex.net:80/get-maps_mrc_public/200212/mrc/"
       "house_number/6775/19262385",
        "http://storage.mds.yandex.net:80/get-maps_mrc_public/222994/mrc/"
        "house_number/1373/25366186",
        "http://storage.mds.yandex.net:80/get-maps_mrc_public/222994/mrc/"
        "house_number/1894/27344527",
        "http://storage.mds.yandex.net:80/get-maps_mrc_public/222994/mrc/"
        "house_number/4496/28504364",
        "http://storage.mds.yandex.net:80/get-maps_mrc_public/264598/mrc/"
        "house_number/3306/29280905"};

void replaceAll(
    std::string& str, const std::string& from, const std::string& to)
{
    size_t start_pos = 0;
    while ((start_pos = str.find(from, start_pos)) != std::string::npos) {
        str.replace(start_pos, from.length(), to);
        start_pos += to.length();
    }
}

std::string adjustUrls(
    const std::string& json, const std::vector<std::string>& urls)
{
    auto result = json;
    for (size_t i = 0; i < std::size(URLS); ++i) {
        replaceAll(result, URLS[i], urls[i]);
    }
    return result;
}

} // anonymous namespace

struct Test : testing::Test {
    using TestFixture
        = unittest::WithUnittestConfig<unittest::MdsStubFixture>;

    Test() { testFixture_.reset(new TestFixture); }

    std::unique_ptr<TestFixture> testFixture_;
};

    TEST_F(Test, test)
    {
        auto cfg = testFixture_->config();
        auto mds = testFixture_->config().makePublicMdsClient();
        std::vector<std::string> urls;
        for (size_t id = 1; id <= std::size(URLS); ++id) {
            auto res = mds.post("tst/" + std::to_string(id), IMAGE);
            urls.push_back(mds.makeReadUrl(res.key()));
        }
        auto inputJson
            = json::Value::fromString(adjustUrls(INPUT_JSON, urls));
        auto urlToHouseNumbersMap = aggregateHouseNumbers(inputJson);
        std::ostringstream os;
        dump(urlToHouseNumbersMap, os);
        auto result = json::Value::fromString(os.str());
        auto outputJson
            = json::Value::fromString(adjustUrls(OUTPUT_JSON, urls));
        auto lhs = result["images_with_objects"];
        auto rhs = outputJson["images_with_objects"];
        EXPECT_TRUE(std::is_permutation(
            lhs.begin(), lhs.end(), rhs.begin(), rhs.end()));
    }

} // maps::mrc::tools::test
