#include <yandex/maps/wiki/revision/snapshot_id.h>
#include <yandex/maps/wiki/revision/commit.h>
#include <yandex/maps/wiki/revision/common.h>
#include "snapshot_id_impl.h"
#include "common.h"

#include <maps/libs/common/include/exception.h>
#include <maps/libs/common/include/pimpl_utils.h>

namespace maps::wiki::revision {

DBID SnapshotId::approveOrder() const
{
    REQUIRE(
        impl_->approveOrder,
        "approveOrder isn't initialized"
    );
    return *impl_->approveOrder;
}

DBID SnapshotId::commitId() const
{
    return impl_->commitId;
}

bool SnapshotId::hasApproveOrder() const
{
    return static_cast<bool>(impl_->approveOrder);
}

std::ostream& operator<<(std::ostream& stream, const SnapshotId& snapshotId)
{
    if (snapshotId.hasApproveOrder()) {
        stream << "approveOrder=" << snapshotId.approveOrder() << " ";
    }
    stream <<
        "commitId=" << snapshotId.commitId() << " "
    ;
    return stream;
}

bool SnapshotId::empty() const
{
    return (
        (impl_->commitId == 0) ||
        (
            hasApproveOrder() &&
            (approveOrder() == 0)
        )
    );
}

SnapshotId SnapshotId::fromCommit(
    DBID commitId,
    BranchType branchType,
    pqxx::transaction_base& txn
)
{
    if (
        (branchType != BranchType::Approved) ||
        (commitId == 0)
    ) {
        //WARN: not checking for commit state and its branch
        //  to avoid unnecessary database request
        return PImplFactory::create<SnapshotId>(
            std::nullopt,
            commitId
        );
    }

    auto commit = Commit::load(txn, commitId);
    auto approveOrder = commit.approveOrder();
    REQUIRE(
        approveOrder > 0,
        "Can't create snapshotId, commit " << commitId << " isn't in approved branch"
    );
    return PImplFactory::create<SnapshotId>(approveOrder, commitId);
}

COPYABLE_PIMPL_DEFINITIONS(SnapshotId)

} // namespace maps::wiki::revision
