#pragma once

#include <maps/wikimap/mapspro/libs/query_builder/include/join.h>
#include <maps/wikimap/mapspro/libs/query_builder/include/query.h>
#include <maps/wikimap/mapspro/libs/query_builder/include/where_conditions.h>

#include <vector>

namespace maps::wiki::query_builder {

// Supposed usage:
//
// query_builder::SelectQuery(
//    table_name,
//    {id, key},
//    query_builder::WhereConditions()
//         .append(created_at, date, Relation::Greater)
//         .append(key2, value2))
//    .orderBy(...)
//    .offset(...)
//    .limit(...)
//    .asString(txn)/exec(txn);

class SelectQuery : public Query {
public:
    SelectQuery(
        std::string table,
        std::vector<std::string> columns,
        WhereConditions whereConditions = {});

    SelectQuery(
        const JoinSequence& join,
        std::vector<std::string> columns,
        WhereConditions whereConditions = {});

    explicit SelectQuery(
        std::string table,
        WhereConditions whereConditions = {});

    explicit SelectQuery(
        const JoinSequence& join,
        WhereConditions whereConditions = {});

    SelectQuery& distinctOn(std::vector<std::string> columns);
    SelectQuery& groupBy(std::vector<std::string> groupByColumns);
    SelectQuery& orderBy(std::string order);
    SelectQuery& offset(size_t offset);
    SelectQuery& limit(size_t limit);
    SelectQuery& updateSeed();
    SelectQuery& forUpdate();
    SelectQuery& nowait();

    std::string asString(const pqxx::transaction_base& txn) const override;
    pqxx::result exec(pqxx::transaction_base& txn) const;

    auto introspect() const;

private:
    std::string table_;
    std::vector<std::string> columns_;
    WhereConditions whereConditions_;

    std::vector<std::string> distinctOnColumns_;
    std::vector<std::string> groupByColumns_;

    std::optional<std::string> order_;
    std::optional<size_t> offset_;
    std::optional<size_t> limit_;
    bool forUpdate_;
    bool updateSeed_;
    bool nowait_;
};

} // namespace maps::wiki::query_builder
