#pragma once

#include <yandex/maps/wiki/social/comment.h>

#include <pqxx/pqxx>

#include <list>
#include <vector>
#include <memory>
#include <optional>

namespace maps::wiki::social {

class Factory;

using CommentTypes = std::list<CommentType>;

namespace comments {

const TUid ANY_CREATED_BY = 0;
const TId ANY_OBJECT_ID = 0;
const auto ANY_FEEDBACK_TASK_ID = std::nullopt;
const TId ANY_AOI_ID = 0;
const TId ANY_COMMIT_ID = 0;
const CommentTypes ANY_TYPE;
const auto ANY_INTERNAL = std::nullopt;

enum class DeletedPolicy { Show, Hide };

} // namespace comments

class CommentsFeedParams
{
public:
    CommentsFeedParams() = default;

    TUid createdBy() const { return createdBy_; }
    TId objectId() const { return objectId_; }
    TId commitId() const { return commitId_; }
    std::optional<TId> feedbackTaskId() const { return feedbackTaskId_; }
    TId aoiId() const { return aoiId_; }
    const CommentTypes& types() const { return types_; }
    CommentTypes& types() { return types_; }
    comments::DeletedPolicy deletedPolicy() const { return deletedPolicy_; }
    std::optional<Comment::Internal> internal() const { return internal_; }

    CommentsFeedParams& setCreatedBy(TUid createdBy);
    CommentsFeedParams& setObjectId(TId objectId);
    CommentsFeedParams& setCommitId(TId commitId);
    CommentsFeedParams& setFeedbackTaskId(std::optional<TId> feedbackTaskId);
    CommentsFeedParams& setAoiId(TId aoiId);
    CommentsFeedParams& setTypes(const CommentTypes& types);
    CommentsFeedParams& setDeletedPolicy(comments::DeletedPolicy deletedPolicy);
    CommentsFeedParams& setInternal(std::optional<Comment::Internal> internal);

private:
    TUid createdBy_ = comments::ANY_CREATED_BY;
    TId objectId_ = comments::ANY_OBJECT_ID;
    TId commitId_ = comments::ANY_COMMIT_ID;
    std::optional<TId> feedbackTaskId_;
    TId aoiId_ = comments::ANY_AOI_ID;
    CommentTypes types_;
    comments::DeletedPolicy deletedPolicy_ = comments::DeletedPolicy::Hide;
    std::optional<Comment::Internal> internal_;
};

class CommentsFeed
{
public:
    size_t count() const;

    std::pair<Comments, HasMore> commentsHead(size_t limit) const;
    std::pair<Comments, HasMore> commentsNewer(TId commentId, size_t limit) const;
    std::pair<Comments, HasMore> commentsOlder(TId commentId, size_t limit) const;

private:
    friend class Factory;
    CommentsFeed(
        pqxx::transaction_base& work,
        const CommentsFeedParams& params);

    std::string whereClause() const;

    pqxx::transaction_base& work_;
    CommentsFeedParams params_;
};

} // namespace maps::wiki::social
