#include "geolocks_checker.h"
#include <maps/wikimap/mapspro/services/editor/src/exception.h>
#include <maps/wikimap/mapspro/services/editor/src/magic_strings.h>

#include <maps/wikimap/mapspro/libs/acl_utils/include/moderation.h>
#include <maps/libs/geolib/include/bounding_box.h>
#include <yandex/maps/wiki/geolocks/geolocks.h>

namespace maps::wiki {

namespace {

DECLARE_ERR_CODE( ERR_LOCKED );

geolib3::BoundingBox geosEnvelopeToBoundingBox(const geos::geom::Envelope& envelope)
{
    return geolib3::BoundingBox(
            geolib3::Point2(envelope.getMinX(), envelope.getMinY()),
            geolib3::Point2(envelope.getMaxX(), envelope.getMaxY()));
}

bool isLocked(
    const BranchContext& branchContext,
    UserContext& userContext,
    const geolib3::BoundingBox& bbox)
{
    const auto locks = geolocks::GeoLock::loadByGeom(
        branchContext.txnCore(), branchContext.branch.id(), bbox);
    if (locks.empty()) {
        return false;
    }

    if (std::any_of(
        locks.begin(), locks.end(),
        [](const auto& lock) { return lock.commitId() > 0; }))
    {
        return true; // has automatical lock
    }

    return !acl_utils::hasRole(userContext.aclUser(branchContext), IGNORE_CUSTOM_GEOLOCKS_ROLE);
}

} // namespace

void checkLockedByGeolocks(
    const BranchContext& branchContext,
    UserContext& userContext,
    const geos::geom::Envelope& envelope)
{
    if (envelope.isNull()) {
        return;
    }

    const auto bbox = geosEnvelopeToBoundingBox(envelope);
    WIKI_REQUIRE(
        !isLocked(branchContext, userContext, bbox),
        ERR_LOCKED,
        "bbox is locked for branch: " << branchContext.branch.id());
}

} // namespace maps::wiki
