#include <maps/wikimap/ugc/account/src/lib/gdpr/takeout_status.h>

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

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

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

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

namespace qbuilder = query_builder;

namespace {

std::optional<Takeout> getIncompleteTakeout(pqxx::transaction_base& txn, Uid uid)
{
    auto query = qbuilder::SelectQuery(
        tables::GDPR_TAKEOUT,
        qbuilder::WhereConditions()
            .append(columns::UID, std::to_string(uid.value()))
            .isNull(columns::COMPLETED_AT)
    ).limit(1);

    auto takeoutRows = query.exec(txn);

    if (!takeoutRows.empty()) {
        return Takeout{takeoutRows[0]};
    } else {
        return std::nullopt;
    }
}

bool uidHasData(pqxx::transaction_base& txn, Uid uid)
{
    auto contributionQuery = qbuilder::SelectQuery(
        tables::CONTRIBUTION,
        {"1"},
        qbuilder::WhereConditions()
            .append(
                columns::UID,
                std::to_string(uid.value()))
    ).limit(1);

    if (!contributionQuery.exec(txn).empty()) {
        return true;
    }

    auto assignmentQuery = qbuilder::SelectQuery(
        tables::ASSIGNMENT,
        {"1"},
        qbuilder::WhereConditions()
            .append(
                columns::UID,
                std::to_string(uid.value()))
    ).limit(1);

    if (!assignmentQuery.exec(txn).empty()) {
        return true;
    }
    return false;
}

std::optional<Takeout> getLastCompletedTakeout(pqxx::transaction_base& txn, Uid uid)
{
    auto query = qbuilder::SelectQuery(
        tables::GDPR_TAKEOUT,
        qbuilder::WhereConditions()
            .append(columns::UID, std::to_string(uid.value()))
            .notNull(columns::COMPLETED_AT));

    query.orderBy(columns::COMPLETED_AT + " DESC").limit(1);

    auto takeoutRows = query.exec(txn);

    if (!takeoutRows.empty()) {
        return Takeout{takeoutRows[0]};
    } else {
        return std::nullopt;
    }
}

} // namespace

constexpr maps::enum_io::Representations<TakeoutState> TAKEOUT_STATE_REPRESENTATION {
    {TakeoutState::Empty,            "empty"},
    {TakeoutState::ReadyToDelete,    "ready_to_delete"},
    {TakeoutState::DeleteInProgress, "delete_in_progress"},
};
DEFINE_ENUM_IO(TakeoutState, TAKEOUT_STATE_REPRESENTATION);

TakeoutStatus getTakeoutStatus(pqxx::transaction_base& txn, Uid uid)
{
    TakeoutStatus status;

    if (auto incompleteTakeout = getIncompleteTakeout(txn, uid)) {
        status.state = TakeoutState::DeleteInProgress;
        status.updateDate = incompleteTakeout->requestedAt;
    } else if (uidHasData(txn, uid)) {
        status.state = TakeoutState::ReadyToDelete;
    } else {
        status.state = TakeoutState::Empty;

        if (auto lastTakeout = getLastCompletedTakeout(txn, uid)) {
            status.updateDate = lastTakeout->completedAt;
        }
    }

    return status;
}

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