#pragma once

#include "maps/wikimap/mapspro/libs/controller/include/basecontroller.h"
#include "maps/wikimap/mapspro/services/editor/src/approve_status.h"
#include "maps/wikimap/mapspro/services/editor/src/commit.h"

#include <maps/wikimap/mapspro/libs/acl_utils/include/user_kind.h>
#include <yandex/maps/wiki/social/feed.h>
#include <yandex/maps/wiki/social/moderation.h>
#include <yandex/maps/wiki/revision/commit.h>

#include <boost/optional.hpp>

#include <unordered_map>
#include <vector>

namespace maps::wiki {

class GetSocialFeed;
template<>
struct controller::ResultType<GetSocialFeed>
{
    struct EventModel {
        social::Event event;
        CommitModel commitModel;
    };
    std::vector<EventModel> eventModels;

    TBranchId branchId;
    social::FeedType feedType;
    social::TId subscriber;

    std::optional<size_t> totalCount;
    size_t page;
    size_t perPage;
    bool hasMore = false;
};

class GetSocialFeed : public controller::BaseController<GetSocialFeed>
{
public:
    GetSocialFeed();
};

class GetRegularSocialFeedMeta;
template<>
struct controller::ResultType<GetRegularSocialFeedMeta>
{
    StringSet categoryGroups;
};

class GetRegularSocialFeedMeta : public controller::BaseController<GetRegularSocialFeedMeta>
{
public:
    struct Request
    {
        const TUid uid;
        const Token token;
    };

    explicit GetRegularSocialFeedMeta(const Request& request);
    virtual std::string printRequest() const;
private:
    virtual void control();

    const Request request_;
};

class GetRegularSocialFeed : public GetSocialFeed
{
public:
    enum class PreApprovedOnly { No, Yes };
    enum class WithTotal { No, Yes };

    struct Request
    {
        const TUid uid;
        const TBranchId branchId;
        const social::FeedType feedType;
        const social::TId subscriber;
        const boost::optional<std::string> categoryGroup;
        const std::vector<acl_utils::UserKind> userKinds;
        const PreApprovedOnly preApprovedOnly;
        const size_t page;
        const size_t perPage;
        const social::TId beforeEventId;
        const social::TId afterEventId;
        const Token token;
        const WithTotal withTotal;
        const boost::optional<chrono::TimePoint> since;
        const boost::optional<chrono::TimePoint> till;
    };

    explicit GetRegularSocialFeed(const Request& request);

    virtual std::string printRequest() const;

private:
    std::string printPreApprovedOnly() const;
    virtual void control();

    const Request request_;
};


class GetSuspiciousSocialFeed : public GetSocialFeed
{
public:
    struct Request
    {
        const TUid uid;
        const TBranchId branchId;
        const std::vector<TUid> targetUids;
        const boost::optional<social::ModerationMode> targetMode;
        const boost::optional<chrono::TimePoint> since;
        const boost::optional<chrono::TimePoint> till;
        const std::vector<social::FeedAction> allowedActions;

        const size_t perPage;
        const social::TId beforeEventId;
        const social::TId afterEventId;
        const Token token;
    };

    explicit GetSuspiciousSocialFeed(const Request& request);

    virtual std::string printRequest() const;

private:
    virtual void control();

    const Request request_;
};

} // namespace maps::wiki
