#include <maps/wikimap/ugc/backoffice/src/gdpr/lib/dbqueries.h>

#include <maps/wikimap/ugc/libs/common/constants.h>
#include <maps/wikimap/ugc/libs/common/dbqueries.h>

#include <maps/wikimap/mapspro/libs/query_builder/include/delete_query.h>
#include <maps/wikimap/mapspro/libs/query_builder/include/select_query.h>
#include <maps/wikimap/mapspro/libs/query_builder/include/update_query.h>

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

#include <vector>

namespace maps::wiki::ugc::backoffice::gdpr {

maps::wiki::query_builder::SelectQuery loadIncompleteTakeoutsQuery()
{
    return maps::wiki::query_builder::SelectQuery(
        tables::GDPR_TAKEOUT,
        maps::wiki::query_builder::WhereConditions()
            .isNull(columns::COMPLETED_AT));
}

std::vector<ugc::gdpr::Takeout> loadIncompleteTakeouts(pqxx::transaction_base& txn)
{
    auto query = loadIncompleteTakeoutsQuery();

    std::vector<ugc::gdpr::Takeout> result;
    for (const auto& row : query.exec(txn)) {
        result.emplace_back(row);
    }

    return result;
}

std::vector<ugc::gdpr::Takeout> loadIncompleteTakeouts(pgpool3::Pool& pool)
{
    auto txn = pool.slaveTransaction();
    return loadIncompleteTakeouts(*txn);
}

maps::wiki::query_builder::UpdateQuery setTakeoutCompletedQuery(
    const ugc::gdpr::TakeoutId& takeoutId,
    const maps::chrono::TimePoint& now)
{
    maps::wiki::query_builder::UpdateQuery query(
        tables::GDPR_TAKEOUT,
        maps::wiki::query_builder::WhereConditions().appendQuoted(
            columns::TAKEOUT_ID, std::to_string(takeoutId.value())));

    query.appendQuoted(
        columns::COMPLETED_AT,
        maps::chrono::formatSqlDateTime(now));

    return query;
}

void setTakeoutCompleted(
    pgpool3::Pool& pool,
    const ugc::gdpr::TakeoutId& takeoutId,
    bool dryRun)
try {
    const auto now = maps::chrono::TimePoint::clock::now();
    auto txn = pool.masterWriteableTransaction();

    setTakeoutCompletedQuery(takeoutId, now).exec(*txn);

    finishTxn(*txn, dryRun);
} catch (const std::exception& e) {
    ERROR()
        << "Caught exception on update status for takeout status of takeout id "
        << takeoutId.value() << ". Error: " << e.what();
}

void removeTableUserData(
    pqxx::transaction_base& txn,
    const std::string& table,
    Uid uid,
    const maps::chrono::TimePoint& requestedAt)
{
    auto deleteQuery = maps::wiki::query_builder::DeleteQuery(
        table,
        maps::wiki::query_builder::WhereConditions()
            .append(columns::UID, std::to_string(uid.value()))
            .appendQuoted(
                columns::CREATED_AT,
                maps::chrono::formatSqlDateTime(requestedAt),
                maps::wiki::query_builder::Relation::LessOrEqual)
    );

    deleteQuery.exec(txn);
}

} // namespace maps::wiki::ugc::backoffice::gdpr
