#include <maps/wikimap/mapspro/services/mrc/tools/collect_traffic_signs/executor/context.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/log8/include/log8.h>
#include <maps/wikimap/mapspro/services/mrc/libs/common/include/opencv.h>
#include <maps/wikimap/mapspro/services/mrc/libs/db/include/feature_gateway.h>
#include <yandex/maps/mrc/unittest/database_fixture.h>
#include <yandex/maps/mrc/unittest/local_server.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/collect_traffic_signs/"
                                            "executor/tests";

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

const std::string URLS[]
    = {"http://storage.mds.yandex.net:80/get-maps_mrc_public/"
       "222994/toloka-mgr/task/6042363",
       "http://storage.mds.yandex.net:80/get-maps_mrc_public/"
       "222994/toloka-mgr/task/5778868"};

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 Photos& photos)
{
    EXPECT_EQ(std::size(URLS), photos.size());
    auto result = json;
    for (size_t i = 0; i < std::size(URLS); ++i) {
        replaceAll(result, URLS[i], photos[i].url);
    }
    return result;
}

} // anonymous namespace

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

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

    db::TId makeFeature()
    {
        auto txn = testFixture_->pool().masterWriteableTransaction();
        auto mds = testFixture_->config().makeMdsClient();
        auto feature = sql_chemistry::GatewayAccess<db::Feature>::construct()
                           .setSourceId("iPhone")
                           .setGeodeticPos({37.547148, 55.727823})
                           .setHeading(geolib3::Heading{170.})
                           .setTimestamp(chrono::parseSqlDateTime(
                               "2017-05-17 11:03:17+03"));
        db::FeatureGateway{*txn}.insert(feature);
        auto res = mds.post("tst/" + std::to_string(feature.id()), IMAGE);
        feature.setMdsKey(res.key());
        db::FeatureGateway{*txn}.update(feature, db::UpdateFeatureTxn::Yes);
        txn->commit();
        return feature.id();
    }

    std::unique_ptr<TestFixture> testFixture_;
};

    TEST_F(Test, test)
    {
        auto cfg = testFixture_->config();
        auto ctx = Context(cfg, "nirvana-token");
        db::TIds featureIds;
        for (size_t i = 0; i < std::size(URLS); ++i) {
            featureIds.push_back(makeFeature());
        }

        auto photos = ctx.postToPublicMds(featureIds);
        EXPECT_EQ(photos.size(), std::size(URLS));
        auto inputJson = adjustUrls(INPUT_JSON, photos);

        EXPECT_EQ(json::Value::fromString(inputJson),
                  json::Value::fromString(toInputJson(photos)));
    }

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