#include "has_geobase_id_categories.h"
#include "module.h"

#include <maps/wikimap/mapspro/libs/validator/include/yandex/maps/wiki/validator/check.h>
#include <maps/wikimap/mapspro/libs/validator/include/yandex/maps/wiki/validator/categories.h>
#include <maps/wikimap/mapspro/libs/validator/include/yandex/maps/wiki/validator/objects/name.h>

#include <maps/libs/json/include/value.h>

#include <library/cpp/resource/resource.h>

namespace maps::wiki::validator::checks {

using categories::AD;
using categories::AD_SUBST;
using categories::TRANSPORT_AIRPORT;
using categories::TRANSPORT_METRO_STATION;

constexpr auto CHECK_DATA = "geobase_id_map.json";

using IdToGeobaseIdMap = std::unordered_map<uint64_t, std::string>;

IdToGeobaseIdMap getIdToGeobaseIdMap(CheckContext* context)
{
    IdToGeobaseIdMap id2geobaseId;
    auto checkDataJson = maps::json::Value::fromString(NResource::Find(CHECK_DATA));
    for (const auto& el : checkDataJson["geobase_check"]) {
        const auto id = el["id"].as<uint64_t>();
        const auto geobaseId = el["geobase_id"].as<std::string>();
        if (id2geobaseId.contains(id) && id2geobaseId.at(id) != geobaseId) {
            context->fatal("invalid-geobase-id-check", boost::none, {});
        }
        id2geobaseId[id] = geobaseId;
    }
    return id2geobaseId;
}

template<class CategoryName>
bool checkGeobaseId(CheckContext* context, const IdToGeobaseIdMap& id2geobaseId)
{
    context->objects<CategoryName>().visit([&](const typename CategoryName::TObject* object) {
        auto id = object->id();
        if (id2geobaseId.contains(id)) {
            if (object->geobaseId() != id2geobaseId.at(id)) {
                context->fatal("wrong-geobase-id", boost::none, { object->id() });
            }
        }
    });
    return true;
}

template<class... Categories>
void performChecks(CheckContext* context)
{
    auto id2geobaseId = getIdToGeobaseIdMap(context);

    auto performed = {checkGeobaseId<Categories>(context, id2geobaseId)...};
    (void)performed;
}

VALIDATOR_SIMPLE_CHECK( geocoder_requirements_geobase_id, HAS_GEOBASE_ID_CATEGORIES )
{
    performChecks<HAS_GEOBASE_ID_CATEGORIES>(context);
}

} // maps::wiki::validator::checks
