#include <maps/wikimap/mapspro/libs/social/magic_strings.h>

#include <yandex/maps/wiki/common/string_utils.h>
#include <yandex/maps/wiki/social/feedback/commits.h>

#include <algorithm>

namespace maps::wiki::social::feedback {

std::unordered_map<TId, TId> taskIdsByCommitIds(
    pqxx::transaction_base& socialTxn,
    TIds commitIds)
{
    if (commitIds.empty()) {
        return {};
    }

    std::stringstream query;
    query << "SELECT " << sql::col::COMMIT_ID << ", " << sql::col::FEEDBACK_TASK_ID
        << " FROM " << sql::table::COMMIT_FEEDBACK_TASK
        << " WHERE " << sql::col::COMMIT_ID << " IN (" << common::join(commitIds, ',') << ")";

    auto rows = socialTxn.exec(query);
    std::unordered_map<TId, TId> result;
    for (const auto& row: rows) {
        result[row[sql::col::COMMIT_ID].as<TId>()] = row[sql::col::FEEDBACK_TASK_ID].as<TId>();
    }
    return result;
}

std::unordered_map<TId, TIds> commitIdsByTaskIds(
    pqxx::transaction_base& socialTxn,
    TIds taskIds)
{
    if (taskIds.empty()) {
        return {};
    }

    std::stringstream query;
    query << "SELECT " << sql::col::COMMIT_ID << ", " << sql::col::FEEDBACK_TASK_ID
        << " FROM " << sql::table::COMMIT_FEEDBACK_TASK
        << " WHERE " << sql::col::FEEDBACK_TASK_ID << " IN (" << common::join(taskIds, ',') << ")";

    auto rows = socialTxn.exec(query);
    std::unordered_map<TId, TIds> result;
    for (const auto& row: rows) {
        result[row[sql::col::FEEDBACK_TASK_ID].as<TId>()].insert(row[sql::col::COMMIT_ID].as<TId>());
    }
    return result;
}

TIds commitIdsByTaskId(
    pqxx::transaction_base& socialTxn,
    TId taskId)
{
    auto result = commitIdsByTaskIds(socialTxn, {taskId});
    if (result.empty()) {
        return TIds{};
    } else {
        return result.begin()->second;
    }
}

void bindCommitsToTask(
    pqxx::transaction_base& socialTxn,
    TId taskId,
    const TIds& commitIds)
{
    std::stringstream query;

    query << "INSERT INTO " << sql::table::COMMIT_FEEDBACK_TASK << " "
        << "("
        << sql::col::COMMIT_ID
        << ", " << sql::col::FEEDBACK_TASK_ID
        << ") VALUES ";

    query << common::join(commitIds, [&taskId](TId commitId){
        std::stringstream ss;
        ss << "(" << commitId << ", " << taskId << ")";
        return ss.str();
    }, ", ");

    socialTxn.exec(query.str());
}

} // namespace maps::wiki::social::feedback
