#include "get_tasks.h"

#include <maps/wikimap/mapspro/services/editor/src/branch_helpers.h>
#include <maps/wikimap/mapspro/services/editor/src/acl_utils.h>
#include <yandex/maps/wiki/common/string_utils.h>

namespace maps::wiki {
GetSpravTasks::GetSpravTasks(const Request& request)
    : controller::BaseController<GetSpravTasks>(BOOST_CURRENT_FUNCTION)
    , request_(request)
{
    result_->limit = request_.limit;
    result_->offset = request_.offset;
}

std::string
GetSpravTasks::printRequest() const
{
    std::stringstream ss;
    ss << " oid: " << request_.objectId;
    ss << " token: " << request_.token;
    ss << " uid: " << request_.user;
    ss << " offset: " << request_.offset;
    ss << " limit: " << request_.limit;
    return ss.str();
}

void
GetSpravTasks::control()
{
    auto branchCtx = BranchContextFacade().acquireReadCoreSocial(request_.token);
    getUser(branchCtx, request_.user).checkNotDeletedStatus();
    auto& txn = branchCtx.txnSocial();
    std::stringstream totalQueryStream;

    auto addFilter = [&](std::ostream& query) {
        if (request_.createdBy) {
            query << " AND created_by=" << request_.createdBy;
        }
        if (request_.objectId) {
            query << " AND object_id=" << request_.objectId;
        }
        if (!request_.statuses.empty()) {
            auto statuses = request_.statuses;
            if (std::find(statuses.begin(), statuses.end(), SpravTask::Status::New) != statuses.end()) {
                statuses.push_back(SpravTask::Status::NotSubmitted);
            }
            query
                << " AND sprav_status IN ("
                << common::join(
                    statuses,
                    [&](const auto status) {
                        return txn.quote(boost::lexical_cast<std::string>(status));
                    },
                    ',')
                <<")";
        }
    };
    totalQueryStream << "SELECT count(*) FROM " + SPRAV_TASKS_TABLE + " WHERE TRUE ";
    addFilter(totalQueryStream);
    result_->total = txn.exec(totalQueryStream.str())[0][0].as<size_t>();
    if (request_.offset >= result_->total) {
        return;
    }
    std::stringstream tasksQueryStream;
    tasksQueryStream << "SELECT * FROM " + SPRAV_TASKS_TABLE + " WHERE TRUE ";
    addFilter(tasksQueryStream);
    tasksQueryStream
        << " ORDER BY task_id DESC LIMIT "
        << request_.limit << " OFFSET " << request_.offset;
    auto rows = txn.exec(tasksQueryStream.str());
    for (const auto& row : rows) {
        result_->tasks.emplace_back(row);
    }
}

} // namespace maps::wiki
