#include "feed.h"
#include <maps/wikimap/mapspro/services/editor/src/configs/config.h>
#include <maps/wikimap/mapspro/services/editor/src/branch_helpers.h>

#include <maps/wikimap/mapspro/libs/acl_utils/include/caching_acl.h>
#include <maps/wikimap/mapspro/libs/acl_utils/include/feedback.h>
#include <yandex/maps/wiki/common/paged_result.h>
#include <yandex/maps/wiki/social/gateway.h>
#include <yandex/maps/wiki/social/feedback/gateway_ro.h>

namespace maps {
namespace wiki {

GetCommentsFeed::GetCommentsFeed(const Request& request)
    : controller::BaseController<GetCommentsFeed>(BOOST_CURRENT_FUNCTION)
    , request_(request)
{}

std::string
GetCommentsFeed::printRequest() const
{
    std::stringstream ss;
    ss << request_.params.dump()
       << " per-page: " << request_.perPage
       << " older-than-id: " << request_.olderThanCommentId
       << " newer-than-id: " << request_.newerThanCommentId
       << " token: " << request_.token;
    return ss.str();
}

void
GetCommentsFeed::control()
{
    WIKI_REQUIRE(
        !(request_.newerThanCommentId && request_.olderThanCommentId),
        ERR_BAD_REQUEST,
        "Both before and after cannot be set"
    );

    auto tokenSocial = getSocialToken(request_.token);
    auto workSocial = cfg()->poolSocial().slaveTransaction(tokenSocial);

    auto params = request_.params.commentsFeedParams();

    if (params.feedbackTaskId()) {
        social::feedback::GatewayRO gatewayRo(workSocial.get());
        auto feedbackTask =
            gatewayRo.taskById(*params.feedbackTaskId());
        auto history = gatewayRo.history(feedbackTask->id());

        WIKI_REQUIRE(
            feedbackTask,
            ERR_NOT_FOUND,
            "Feedback with id '" << feedbackTask->id() << "'" <<
            "doesn't exist"
        );

        auto uid = request_.params.uid();

        static const size_t CACHE_SIZE = 10;
        static const auto CACHE_EXPIRATION_PERIOD = std::chrono::seconds(10);
        acl_utils::CachingAclChecker aclChecker(cfg()->poolCore(), CACHE_SIZE, CACHE_EXPIRATION_PERIOD);
        acl_utils::FeedbackPresetCheckerImpl fbPresetChecker(
            cfg()->poolCore(), cfg()->poolSocial(),
            CACHE_SIZE, CACHE_EXPIRATION_PERIOD);
        acl_utils::FeedbackChecker feedbackChecker(
            aclChecker,
            fbPresetChecker
        );
        WIKI_REQUIRE(
            feedbackChecker.isAllowedToView(
                *feedbackTask,
                history,
                uid
            ),
            ERR_FORBIDDEN,
            "Feedback with id '" << feedbackTask->id() << "'" <<
            " and its comments are not allowed for user '" << uid << "'"
        );
    }

    auto feed = social::Gateway(*workSocial).commentsFeed(params);

    auto commentsPage =
        request_.olderThanCommentId ?
            feed.commentsOlder(request_.olderThanCommentId, request_.perPage) :
                request_.newerThanCommentId ?
                    feed.commentsNewer(request_.newerThanCommentId, request_.perPage) :
                    feed.commentsHead(request_.perPage);

    result_->comments = std::move(commentsPage.first);
    result_->hasMore = commentsPage.second;
    result_->totalCount = feed.count();
}

} // namespace wiki
} // namespace maps
