#include <yandex/maps/wiki/tasks/commit_sync.h>

namespace maps {
namespace wiki {
namespace tasks {

using CommitVec = std::vector<CommitId>;

std::ostream& operator<<(std::ostream& out, CommitStatus status)
{
    switch (status) {
        case CommitStatus::NotSynced: return out << "false";
        case CommitStatus::Synced: return out << "true";
    }

    throw CommitRecordInvalid()
        << "Invalid commit status: " << static_cast<int>(status);
}

CommitRecordGateway::CommitRecordGateway(
    pgpool3::TransactionHandle& txn,
    std::string tableName)
        : txn_(txn)
        , tableName_(std::move(tableName))
{
}

CommitRecord
CommitRecordGateway::getCommit(TaskId taskId, CommitId commitId) const
{
    auto commits = getCommits(taskId, CommitVec{commitId});
    if (commits.size() < 1) {
        throw CommitRecordNotFound(taskId, commitId);
    }
    return std::move(commits[0]);
}

CommitRecords
CommitRecordGateway::getCommits(TaskId taskId) const
{
    return getCommitsInternal<CommitVec>(taskId, boost::none);
}

void
CommitRecordGateway::addCommit(const CommitRecord& entry)
{
    addCommits(entry.taskId, CommitVec{entry.commitId}, entry.status);
}

bool
CommitRecordGateway::removeCommit(TaskId taskId, CommitId commitId)
{
    return removeCommits(taskId, CommitVec{commitId});
}

std::size_t
CommitRecordGateway::removeCommits(TaskId taskId)
{
    std::ostringstream query;
    query << "DELETE FROM " << tableName_ << "\n"
          << "WHERE " << sql::col::TASK_ID << " = " << taskId << ";";
    auto result = txn_->exec(query.str());
    return result.affected_rows();
}

void
CommitRecordGateway::updateStatus(
    TaskId taskId,
    CommitId commitId,
    CommitStatus status)
{
    auto numUpdated = updateStatus(taskId, CommitVec{commitId}, status);

    if (numUpdated < 1) {
        throw CommitRecordNotFound(taskId, commitId);
    }
}

} // namespace tasks
} // namespace wiki
} // namespace maps

