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

#include <maps/wikimap/mapspro/libs/common/include/yandex/maps/wiki/common/string_utils.h>

namespace maps::wiki::query_builder {

UpdateOnConflict::UpdateOnConflict(
    WhereConditions whereConditions)
    : UpdateQuery("", std::move(whereConditions))
{}

OnConflict::OnConflict(
    std::optional<std::string> constraint,
    std::vector<std::string> columns,
    UpdateOnConflict updateOnConflict,
    WhereConditions whereConditions)
    : constraint_{std::move(constraint)}
    , columns_{std::move(columns)}
    , updateOnConflict_{std::move(updateOnConflict)}
    , whereConditions_{std::move(whereConditions)}
{
}

OnConflict OnConflict::fromColumns(
    std::vector<std::string> columns,
    UpdateOnConflict updateOnConflict,
    WhereConditions whereConditions)
{
    return OnConflict{
        std::nullopt,
        std::move(columns),
        std::move(updateOnConflict),
        std::move(whereConditions)
    };
}

OnConflict OnConflict::fromConstraint(
    std::string constraint,
    UpdateOnConflict updateOnConflict,
    WhereConditions whereConditions)
{
    return OnConflict{
        std::move(constraint),
        {},
        std::move(updateOnConflict),
        std::move(whereConditions)
    };
}

std::string OnConflict::asString(const pqxx::transaction_base& txn) const
{
    std::ostringstream result;
    result << "ON CONFLICT ";
    if (!columns_.empty()) {
        result << "(" << maps::wiki::common::join(columns_, ", ") << ")";
    } else if (constraint_) {
        result << "ON CONSTRAINT " << *constraint_;
    }
    result << (whereConditions_.empty() ? "" : " " + whereConditions_.asString(txn)) << " DO ";
    if (updateOnConflict_.empty()) {
        result << "NOTHING";
    } else {
        result << updateOnConflict_.asString(txn);
    }
    return result.str();
}

} // namespace maps::wiki::query_builder
