#include <maps/wikimap/mapspro/libs/social/feedback/workflow_logic.h>
#include <maps/wikimap/mapspro/services/social/src/libs/feedback-actions/tasks_poi.h>
#include <yandex/maps/wiki/social/feedback/attribute_names.h>

namespace maps::wiki::socialsrv {

namespace mwsf = social::feedback;
namespace mwsfa = social::feedback::attrs;

namespace {

bool isTwinTaskByEqualObjects(
    pqxx::transaction_base& txn,
    const mwsf::TaskNew& task)
{
    if (task.objectId == std::nullopt) {
        return false;
    }

    auto subSource = [&](const mwsf::Attrs& attrs) -> std::string {
        if (attrs.existCustom(mwsfa::SUBSOURCE)) {
            return attrs.getCustom(mwsfa::SUBSOURCE);
        }
        return "";
    };

    mwsf::GatewayRO gatewayRo(txn);
    mwsf::TaskFilter twinFilter;
    twinFilter.objectId(*task.objectId);
    twinFilter.workflow(mwsf::workflow(task));
    auto existingTasks = gatewayRo.tasksByFilter(twinFilter);

    auto twin = std::find_if(existingTasks.begin(), existingTasks.end(),
        [&](const mwsf::Task& exTask) {
            return exTask.source() == task.source &&
                   subSource(exTask.attrs()) == subSource(task.attrs) &&
                   exTask.type() == task.type;
        }
    );

    return twin != existingTasks.end();
}

} // namespace

PostTaskResult createPoiTask(
    DbPools& dbPools,
    const social::feedback::TaskNew& newTask)
{
    if (mwsf::workflow(newTask) == mwsf::Workflow::Task &&
        newTask.objectId && *newTask.objectId)
    {
        auto txn = dbPools.socialReadTxn();
        if (isTwinTaskByEqualObjects(*txn, newTask)) {
            throw Error(Error::Status::Duplicate)
                << "Hypothesis already exists for: " << *newTask.objectId;
        }
    }

    return postNewTask(dbPools, newTask);
}

} // namespace maps::wiki::socialsrv
