#include <yandex/maps/wiki/social/date_time_condition.h>

namespace maps::wiki::social {

DateTimeCondition::DateTimeCondition(std::optional<chrono::TimePoint> first, std::optional<chrono::TimePoint> last):
    first_(std::move(first)),
    last_(std::move(last))
{
    REQUIRE(
        !first || !last || *first <= *last,
        "Wrong time interval " << chrono::formatIsoDateTime(*first) << " - " << chrono::formatIsoDateTime(*last));
}

std::optional<DateTimeCondition>
DateTimeCondition::makeOptional(std::optional<chrono::TimePoint> first, std::optional<chrono::TimePoint> last)
{
    return first || last ? std::make_optional(DateTimeCondition(first, last)) : std::nullopt;
}

std::string DateTimeCondition::sqlComparison(
    pqxx::transaction_base& txn,
    const std::string& expr) const
{
    if (first_ && last_) {
        return
            "(" +
                sqlCompareOp(txn, expr, *first_, " >= ") + " AND " +
                sqlCompareOp(txn, expr, *last_, " < ") +
            ")";
    }
    if (first_) {
        return "(" + sqlCompareOp(txn, expr, *first_, " >= ") + ")";
    }
    if (last_) {
        return "(" + sqlCompareOp(txn, expr, *last_, " < ") + ")";
    }
    return "TRUE";
}

std::string DateTimeCondition::sqlCompareOp(
    pqxx::transaction_base& txn,
    const std::string& expr,
    chrono::TimePoint dateTime,
    const std::string& op)
{
    return "(" + expr + ")" + op + txn.quote(chrono::formatSqlDateTime(dateTime));
}

} // namespace maps::wiki::social
