#include "database.h"

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

namespace maps::wiki::yang {

Database::Database(const common::ExtendedXmlDoc& config)
    : socialPool_(config, "social", "grinder")
{}

bool Database::saveAssignment(PoolId poolId, const Assignment& assignment)
{
    const auto& assignmentId = assignment.id();
    INFO() << "Saving " << assignmentId;
    ASSERT(!assignment.data().empty());

    auto txn = socialPool_.pool().masterWriteableTransaction();
    std::string fields, values;
    for (const auto& [key, value] : assignment.data()) {
        fields += ", " + key;
        values += ", " + txn->quote(value);
    }

    auto query =
        "INSERT INTO yang.assignment"
        " (assignment_id, pool_id" + fields + ") VALUES (" +
            txn->quote(assignmentId) + ", " + std::to_string(poolId) + values + ")"
        " ON CONFLICT DO NOTHING";

    if (!txn->exec(query).affected_rows()) {
        INFO() << "Already exists " << assignmentId;
        return false;
    }
    txn->commit();
    return true;
}

std::map<AttachmentId, PhotoId> Database::loadSavedPhotoIds(
    const Assignment& assignment)
{
    auto txn = socialPool_.pool().slaveTransaction();

    auto query =
        "SELECT attachment_id, photo_id"
        " FROM yang.assignment_photo"
        " WHERE assignment_id = " + txn->quote(assignment.id());

    std::map<AttachmentId, PhotoId> result;
    for (const auto& row : txn->exec(query)) {
        result.emplace(row[0].as<std::string>(), row[1].as<std::string>());
    }
    return result;
}

bool Database::saveAttachments(
    const Assignment& assignment,
    const std::map<AttachmentId, PhotoId>& attachmentToPhotoIds)
{
    REQUIRE(!attachmentToPhotoIds.empty(),
            "Empty photo ids, " << assignment.id());

    auto txn = socialPool_.pool().masterWriteableTransaction();

    std::string values;
    for (const auto& [attachmentId, photoId] : attachmentToPhotoIds) {
        values += values.empty() ? "" : ", ";
        values += "(" +
            txn->quote(assignment.id()) + "," +
            txn->quote(attachmentId) + "," +
            txn->quote(photoId) +
        ")";
    }

    auto query =
        "INSERT INTO yang.assignment_photo ("
        "assignment_id, attachment_id, photo_id) VALUES " + values;
    txn->exec(query);
    txn->commit();
    return true;
}

} // namespace maps::wiki::yang
