#include "common.h"

#include <maps/wikimap/mapspro/services/mrc/libs/fb/include/coverage_rtree_reader.h>
#include <maps/wikimap/mapspro/services/mrc/libs/fb/include/coverage_rtree_writer.h>
#include <maps/wikimap/mapspro/services/mrc/libs/fb/include/version.h>

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

#include <algorithm>

namespace maps::mrc::fb::tests {

TEST(coverage_rtree, base)
{
    auto bbox =
        geolib3::BoundingBox{{37.668694, 55.727076}, {37.671280, 55.729366}};

    auto time = chrono::parseSqlDateTime("2021-09-06 11:12:15");
    auto edgeCoverage =
        TEdgeCoverage{.coverageFraction = 0.5f,
                      .actualizationDate = time,
                      .coveredSubpolylines = {{
                          1,
                          {0, 0.1},
                          {0, 0.2},
                      }},
                      .cameraDeviation = db::CameraDeviation::Front,
                      .privacy = db::FeaturePrivacy::Public};
    auto graphCoverage = TGraph{.version = std::string{roadGraph().version()},
                                .mrcVersion = makeVersion(time)};
    auto fcToCount = std::vector<size_t>(FC_MAX - FC_MIN + 1);
    for (auto edgeId : rtree().edgesInWindow(bbox)) {
        graphCoverage.edges.push_back(
            TEdge{.id = edgeId.value(), .coverages = {edgeCoverage}});
        auto edgeData = roadGraph().edgeData(edgeId);
        auto fc = db::TFc(edgeData.category());
        ++fcToCount[fc - FC_MIN];
    }
    EXPECT_GT(graphCoverage.edges.size(), 0u);
    size_t totalSum = std::accumulate(fcToCount.begin(), fcToCount.end(), 0);
    std::partial_sum(fcToCount.begin(), fcToCount.end(), fcToCount.begin());
    writeCoverageRtreeToDir(roadGraph(), graphCoverage, TEST_PATH);
    auto reader = CoverageRtreeReader{roadGraph(), TEST_PATH};
    EXPECT_EQ(graphCoverage.version, reader.version());
    auto limit = fcToCount.back();

    for (db::TFc fc = FC_MIN; fc <= FC_MAX; ++fc) {
        SCOPED_TRACE("fc = " + std::to_string(fc));
        auto range = reader.getCoveredEdgeIdsByBbox(bbox, fc);
        EXPECT_EQ(std::distance(range.begin(), range.end()),
            static_cast<int>(fcToCount[fc - FC_MIN]));

        EXPECT_EQ(
            reader.getNearestCoveredEdgeIds(bbox.center(), limit, fc).size(),
            fcToCount[fc - FC_MIN]);
    }

    auto allIdsRange = reader.getCoveredEdgeIds();
    EXPECT_EQ(std::distance(allIdsRange.begin(), allIdsRange.end()),
        static_cast<int>(totalSum));
}

}  // namespace maps::mrc::fb::tests
