#pragma once

#include <yandex/maps/wiki/revision/common.h>
#include <yandex/maps/wiki/revision/commit.h>
#include <yandex/maps/wiki/revision/range.h>

namespace maps::wiki::revision {

struct RevertData {
    Commit createdCommit;
    DBIDSet revertedCommitIds;
};

enum class ContributingCommitsOption { Reference, Revert };
using ContributingCommitsOptions = std::set<ContributingCommitsOption>;

enum class SearchPredicateResult {
    Stop,                       ///< Return commits found so far by
                                ///< a CommitManager::find...Commits(..., resultChecker) method.
    Continue                    ///< Look for more commits if possible.
};
using ResultChecker = std::function<SearchPredicateResult(const DBIDSet&)>;
const auto RESULT_CHECKER_DUMMY = [](const DBIDSet&) { return SearchPredicateResult::Continue; };

/**
 * Detailed description and definitions:
 * https://wiki.yandex-team.ru/maps/dev/core/wikimap/mapspro/revert
 * https://wiki.yandex-team.ru/maps/dev/core/wikimap/mapspro/approve
 */
class CommitManager {
public:
    explicit CommitManager(pqxx::transaction_base& work);

    bool hasDraftContributingCommitsWithoutOriginal(
        const ConstRange<DBID>& commitIds) const;
    bool hasDraftContributingCommitsWithoutOriginal(
        const ConstRange<DBID>& commitIds,
        const DBIDSet& excludeCommitIds) const;

    DBIDSet findAllDraftContributingCommits(
        const ConstRange<DBID>& commitIds) const;
    DBIDSet findAllDraftContributingCommits(
        const ConstRange<DBID>& commitIds,
        const DBIDSet& excludeCommitIds) const;

    DBIDSet findDraftContributingCommits(
        const ConstRange<DBID>& commitIds,
        const ContributingCommitsOptions& options) const;

    // return approved commit ids set
    DBIDSet approve(const ConstRange<DBID>& commitIds) const;
    DBIDSet approveAll(DBID maxCommitId) const;

    bool hasDependentCommitsInTrunk(const ConstRange<DBID>& commitIds) const;

    DBIDSet findDependentCommitsInTrunk(
        const ConstRange<DBID>& commitIds,
        const ResultChecker& resultChecker = RESULT_CHECKER_DUMMY) const;

    RevertData revertCommitsInTrunk(
        const ConstRange<DBID>& commitIds,
        UserID userId,
        const Attributes& commitAttributes) const;

    // return new stable commits
    DBIDSet mergeApprovedToStable(DBID maxCommitId) const;

private:
    pqxx::transaction_base& work_;
};

} // namespace maps::wiki::revision
