#include "create.h"

#include <maps/wikimap/mapspro/libs/assessment/impl/sql_helpers.h>
#include <maps/wikimap/mapspro/libs/assessment/impl/magic_strings.h>
#include <maps/wikimap/mapspro/libs/common/include/yandex/maps/wiki/common/string_utils.h>

namespace maps::wiki::assessment::samples {

namespace {

TId insertTask(pqxx::transaction_base& txn, TId sampleId, TId unitId)
{
    const auto result = txn.exec(
       "INSERT INTO " + sql::table::SAMPLE_TASK + " " +
            "(" + sql::col::SAMPLE_ID + ", " + sql::col::UNIT_ID + ") "
        "VALUES " +
            "(" + std::to_string(sampleId) + ", " + std::to_string(unitId) + ") "
        "RETURNING " +
            sql::col::SAMPLE_TASK_ID);

    REQUIRE(
        result.size() == 1,
        "Inserted " << result.size() << " sample tasks "
        "for sample_id=" << sampleId << " unit_id=" << unitId);

    return result[0][sql::col::SAMPLE_TASK_ID].as<TId>();
}

std::string sqlTaskCompetenceRows(TId taskId, const TIds& competenceIds)
{
    std::vector<std::string> rows;
    for (auto competenceId : competenceIds) {
        rows.emplace_back("(" + std::to_string(taskId) + ", " + std::to_string(competenceId) + ")");
    }
    return common::join(rows, ", ");
}

void insertTaskCompetences(pqxx::transaction_base& txn, TId taskId, const TIds& competenceIds)
{
    const auto result = txn.exec(
        "INSERT INTO " + sql::table::SAMPLE_TASK_COMPETENCE + " " +
            "(" + sql::col::SAMPLE_TASK_ID + ", " + sql::col::COMPETENCE_ID + ") "
        "VALUES " +
            sqlTaskCompetenceRows(taskId, competenceIds));

    REQUIRE(
        result.affected_rows() == competenceIds.size(),
        "Inserted " << result.affected_rows() << " "
        "for competenceIds=" << common::join(competenceIds, ","));
}

} // namespace

TId create(pqxx::transaction_base& txn,
    Entity::Domain domain,
    Qualification qualification,
    const std::string& name)
{
    const auto result = txn.exec(
        "INSERT INTO " + sql::table::SAMPLE + " "
        "(" +
            sql::col::ENTITY_DOMAIN + ", " +
            sql::col::QUALIFICATION + ", " +
            sql::col::NAME +
        ") "
        "VALUES "
        "(" +
            sqlEnumToString(txn, domain) + ", " +
            sqlEnumToString(txn, qualification) + ", " +
            txn.quote(name) +
        ") "
        "RETURNING " +
            sql::col::SAMPLE_ID);

    REQUIRE(result.size() == 1, "Inserted unexpected number of samples: " << result.size());
    return result[0][sql::col::SAMPLE_ID].as<TId>();
}


TId createTask(
    pqxx::transaction_base& txn,
    TId sampleId,
    TId unitId,
    const TIds& competenceIds)
{
    const auto taskId = insertTask(txn, sampleId, unitId);
    if (!competenceIds.empty()) {
        insertTaskCompetences(txn, taskId, competenceIds);
    }
    return taskId;
}

} // maps::wiki::assessment::samples
