#include "common.h"
#include "fixture.h"

#include <library/cpp/testing/gmock_in_unittest/gmock.h>
#include <library/cpp/testing/unittest/env.h>
#include <library/cpp/testing/unittest/registar.h>
#include <maps/infra/yacare/include/test_utils.h>
#include <maps/infra/yacare/include/yacare.h>
#include <maps/libs/concurrent/include/scoped_guard.h>
#include <maps/libs/log8/include/log8.h>
#include <maps/wikimap/mapspro/services/mrc/browser/lib/tools.h>

namespace maps::mrc::browser::tests {

namespace {

bool testFeatureExists(db::TId featureId) {
    http::MockRequest rq(http::GET,
        http::URL("http://localhost/feature/" + std::to_string(featureId) + "/image")
    );
    auto resp = yacare::performTestRequest(rq);
    return resp.status == 200;
}


db::TId addNewFeature(pqxx::transaction_base& txn) {
    auto feature = db::Feature{"source",
                               geolib3::Point2{37.563593, 55.667642},
                               geolib3::Heading(0),
                               "2019-09-16 11:22:00",
                               mds::Key("100500", "unittest/1"),
                               {}}
                       .setSize(1920, 1080)
                       .setAutomaticShouldBePublished(true)
                       .setIsPublished(true)
                       .setCameraDeviation(db::CameraDeviation::Front)
                       .setPrivacy(db::FeaturePrivacy::Public);

    db::FeatureGateway{txn}.insert(feature);
    db::updateFeatureTransaction(feature, txn);
    txn.commit();

    return feature.id();
}


} // namespace

Y_UNIT_TEST_SUITE(service_api_should) {

Y_UNIT_TEST(test_dataset_reload)
{
    FixtureFb fixture;

    // at this time GET /ping behaiour can't be tested with performTestRequest
    // auto getPingStatus = []() {
    //     http::MockRequest rq(http::GET, http::URL("http://localhost/ping"));
    //     auto resp = yacare::performTestRequest(rq);
    //     return resp.status;
    // };

    // EXPECT_EQ(getPingStatus(), 200);
    EXPECT_TRUE(testFeatureExists(1));

    db::TId newFeatureId = addNewFeature(*fixture.txnHandle());
    auto mrcExportPath = fixture.exportToFb();

    {
        http::MockRequest rq(http::POST,
                http::URL("http://localhost/service/reload_dataset")
                    .addParam("dataset", "mrc")
                    .addParam("path", mrcExportPath)
        );
        auto resp = yacare::performTestRequest(rq);
        ASSERT_EQ(resp.status, 200);
    }

    // EXPECT_EQ(getPingStatus(), 503);
    EXPECT_TRUE(testFeatureExists(1));
    EXPECT_FALSE(testFeatureExists(newFeatureId));

    waitTillAllDatasetsLoaded();

    EXPECT_TRUE(testFeatureExists(1));
    EXPECT_TRUE(testFeatureExists(newFeatureId));

}

Y_UNIT_TEST(test_switch_dataset_to_empty_version)
{
    FixtureFb fixture;

    // at this time GET /ping behaviour can't be tested with performTestRequest
    // auto getPingStatus = []() {
    //     http::MockRequest rq(http::GET, http::URL("http://localhost/ping"));
    //     auto resp = yacare::performTestRequest(rq);
    //     return resp.status;
    // };

    // EXPECT_EQ(getPingStatus(), 200);
    EXPECT_TRUE(testFeatureExists(1));

    {
        http::MockRequest rq(http::POST,
                http::URL("http://localhost/service/reload_dataset")
                    .addParam("dataset", "mrc")
        );
        auto resp = yacare::performTestRequest(rq);
        ASSERT_EQ(resp.status, 200);
    }

    // EXPECT_EQ(getPingStatus(), 503);
    EXPECT_TRUE(testFeatureExists(1));

    waitTillAllDatasetsLoaded();

    EXPECT_FALSE(testFeatureExists(1));
}

Y_UNIT_TEST(test_options)
{
    const auto ALLOW_ORIGIN_HEADER = "Access-Control-Allow-Origin";
    const auto YANDEX_ORIGIN = "http://maps.yandex.ru";
    for (const auto& endpoint : {
             "/features/1/path",
             "/features/1/similar",
             "/features/directions",
             "/features/find",
             "/features/hotspot",
             "/features/near",
             "/features/tour_along_route",
             "/tiles",
             "/v2/photo/get",
             "/v2/photos/get",
             "/v2/photo/hotspot",
         }) {
        auto rq = http::MockRequest(
            http::Method{"OPTIONS"},
            http::URL{std::string{"http://localhost"} + endpoint});
        auto resp = yacare::performTestRequest(rq);
        EXPECT_EQ(resp.status, 200);
        EXPECT_FALSE(resp.headers.contains(ALLOW_ORIGIN_HEADER));
        EXPECT_FALSE(resp.headers.contains(ALLOW_METHODS_HEADER));
        rq.headers["Origin"] = YANDEX_ORIGIN;
        resp = yacare::performTestRequest(rq);
        EXPECT_EQ(resp.status, 200);
        EXPECT_EQ(resp.headers.at(ALLOW_ORIGIN_HEADER), YANDEX_ORIGIN);
        EXPECT_EQ(resp.headers.at(ALLOW_METHODS_HEADER), METHODS_GET_OPTIONS);
    }
}

} // Y_UNIT_TEST_SUITE(service_api_should)

} // namespace maps::mrc::browser::tests
