#include "fixture.h"

#include <library/cpp/testing/gtest/gtest.h>
#include <maps/libs/local_postgres/include/instance.h>
#include <maps/wikimap/mapspro/services/mrc/libs/db/include/area_of_interest_gateway.h>
#include <maps/libs/geolib/include/test_tools/comparison.h>

namespace maps::mrc::db::tests {
namespace {

bool isEqual(const AreaOfInterest& lhs, const AreaOfInterest& rhs) {
    return lhs.id() == rhs.id() && lhs.name() == rhs.name()
        && geolib3::test_tools::approximateEqual(lhs.mercatorGeom(), rhs.mercatorGeom(), 0);
}

} // namespace

using geolib3::Polygon2;
using geolib3::MultiPolygon2;
using geolib3::PointsVector;

TEST_F(Fixture, test_area_of_interest) {

    AreaOfInterest a{geolib3::convertGeodeticToMercator(MultiPolygon2{
        {Polygon2{PointsVector{{37.6, 55.6}, {37.7, 55.6}, {37.7, 55.7}, {37.6, 55.6}}}}}), "a"};

    AreaOfInterest b{geolib3::convertGeodeticToMercator(MultiPolygon2{
        {Polygon2{PointsVector{{37.7, 55.7}, {37.7, 55.8}, {37.8, 55.8}, {37.7, 55.7}}}}}), "b"};

    {
        auto txn = txnHandle();
        AoiGateway gtw(*txn);
        gtw.insert(a);
        gtw.insert(b);
        txn->commit();
    }

    {
        auto txn = txnHandle();
        AoiGateway gtw(*txn);
        auto ids = gtw.loadIds();
        std::sort(ids.begin(), ids.end());
        TIds expected = {a.id(), b.id()};
        std::sort(expected.begin(), expected.end());
        EXPECT_EQ(ids, expected);
        EXPECT_TRUE(isEqual(a, gtw.loadById(a.id())));
        EXPECT_TRUE(isEqual(b, gtw.loadById(b.id())));
    }

    AreaOfInterest bChanged = b;
    b.setGeodeticGeom(MultiPolygon2{
        {Polygon2{PointsVector{{38.7, 56.7}, {38.7, 56.8}, {38.8, 56.8}, {38.7, 56.7}}}}});

    {
        auto txn = txnHandle();
        AoiGateway gtw(*txn);
        gtw.update(bChanged);
        txn->commit();
    }

    {
        auto txn = txnHandle();
        AoiGateway gtw(*txn);
        auto bLoaded = gtw.loadById(b.id());
        EXPECT_FALSE(isEqual(b, bLoaded));
        EXPECT_TRUE(isEqual(bChanged, bLoaded));
    }

    {
        auto txn = txnHandle();
        AoiGateway gtw(*txn);
        gtw.removeById(b.id());
        txn->commit();
    }

    {
        auto txn = txnHandle();
        AoiGateway gtw(*txn);
        auto ids = gtw.loadIds();
        EXPECT_EQ(ids.size(), 1u);
        EXPECT_EQ(ids.front(), a.id());
    }
}

} // namespace maps::mrc::db::tests
