#include "operations.h"

#include <maps/wikimap/mapspro/libs/acl/include/aclgateway.h>
#include <yandex/maps/wiki/social/feedback/agent.h>
#include <yandex/maps/wiki/social/feedback/task_aoi.h>

namespace maps::wiki::socialsrv {

using namespace social;
using namespace social::feedback;

namespace {
const std::string LIMITING_ROLE_NAME_PART = "feedback_limit";

TIds getLimitingAoiIds(
    pqxx::transaction_base& coreTxn, TUid uid)
{
    acl::ACLGateway aclGateway(coreTxn);

    const auto limitingRoles = aclGateway.roles(
        acl::InclusionType::Contains, LIMITING_ROLE_NAME_PART);
    TIds limitingRoleIds;
    for (const auto& role: limitingRoles) {
        limitingRoleIds.insert(role.id());
    }
    const auto policies = aclGateway.user(uid).allPolicies();

    TIds result;
    for (const auto& policy: policies) {
        if (limitingRoleIds.count(policy.roleId())) {
            result.insert(policy.aoiId());
        }
    }
    return result;
}

bool isTaskAllowed(
    TId taskId,
    pqxx::transaction_base& socialTxn,
    TUid uid,
    pqxx::transaction_base& coreTxn)
{
    const auto limitingAoiIds = getLimitingAoiIds(coreTxn, uid);
    if (limitingAoiIds.empty()) {
        return true;
    }

    const auto tasksAoiIds = getTasksAoiIds(socialTxn, {taskId});
    if (tasksAoiIds.empty()) {
        return false;
    }
    const auto& taskAoiIds = tasksAoiIds.at(taskId);
    for (auto id: limitingAoiIds) {
        if (taskAoiIds.contains(id)) {
            return true;
        }
    }
    return false;
}

} // namespace

TaskOperations getTaskValidOperations(
    const Task& task,
    pqxx::transaction_base& socialTxn,
    TUid uid,
    pqxx::transaction_base& coreTxn)
{
    if (isTaskAllowed(task.id(), socialTxn, uid, coreTxn)) {
        return Agent::validOperations(task, uid);
    }
    return TaskOperations();
}

} // namespace maps::wiki::socialsrv
