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

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


namespace maps::wiki::query_builder {

constexpr maps::enum_io::Representations<JoinType> JOIN_TYPE_REPRESENTATION {
    {JoinType::Inner, "INNER"},
    {JoinType::Left, "LEFT"},
    {JoinType::Right, "RIGHT"},
    {JoinType::Full, "FULL"},
};
DEFINE_ENUM_IO(JoinType, JOIN_TYPE_REPRESENTATION);

std::string JoinCondition::asString(const std::string& table) const {
    std::ostringstream result;
    result << table << "." << column << " = " << otherTable << "." << otherColumn;
    return result.str();
}

std::string JoinStatement::asString() const {
    std::ostringstream result;
    result << joinType << " JOIN " << table << " ON "
        << maps::wiki::common::join(conditions, [&](const JoinCondition& condition){ return condition.asString(table); }, " AND ");
    return result.str();
}


JoinSequence::JoinSequence(std::string table)
    : table(std::move(table))
{}

JoinSequence& JoinSequence::join(JoinStatement statement) {
    joins.push_back(std::move(statement));
    return *this;
}

std::string JoinSequence::asString() const {
    std::ostringstream result;
    result << table << " "
        << maps::wiki::common::join(joins, [&](const JoinStatement& join){ return join.asString(); }, " ") << " ";
    return result.str();
}

} // namespace maps::wiki::query_builder
