#pragma once

#include <maps/wikimap/mapspro/services/mrc/libs/db/include/ugc/assignment_object.h>
#include <maps/wikimap/mapspro/services/mrc/libs/db/include/assignment_object_feedback_task_gateway.h>

#include <maps/libs/sql_chemistry/include/gateway.h>

namespace maps::mrc::db::ugc {
namespace table {
using namespace sql_chemistry;

struct AssignmentObject : Table<db::ugc::AssignmentObject> {
    static constexpr std::string_view name_{"ugc.assignment_object"sv};

    static constexpr BigSerialKey objectId{"object_id"sv, name_};
    // not null FOREIGN KEY ugc.assignment
    static constexpr NumericColumn<TId> assignmentId{"assignment_id"sv, name_};
    static constexpr TimePointColumn createdAt{"created_at"sv, name_};
    static constexpr GeodeticColumn<geolib3::Point2> position{"position"sv, name_};
    static constexpr EnumColumn<db::ugc::AssignmentObjectType> type{"type"sv, name_};
    static constexpr NullableStringColumn comment{"comment"sv, name_};

    static constexpr auto columns_() {
        return std::tie(objectId, assignmentId, createdAt, position, type, comment);
    }
};

} // namespace table

class AssignmentObjectGateway : public sql_chemistry::Gateway<table::AssignmentObject> {
public:
    using Tb = table::AssignmentObject;
    using JoinedTb = db::table::AssignmentObjectFeedbackTask;
    using Base = Gateway<Tb>;
    using Base::Gateway;
    using Base::Entities;

    Entities loadWithFeedback(std::optional<size_t> limit = std::nullopt, std::size_t offset = 0) {
        return load(Tb::objectId == JoinedTb::objectId && JoinedTb::feedbackTaskId != std::nullopt,
                sql_chemistry::orderBy(Tb::objectId).offset(offset).limit(limit));
    }

    Entities loadWithoutFeedback(std::optional<size_t> limit = std::nullopt, std::size_t offset = 0) {
        return load(Tb::objectId == JoinedTb::objectId && JoinedTb::feedbackTaskId == std::nullopt,
                sql_chemistry::orderBy(Tb::objectId).offset(offset).limit(limit));
    }

    Ids loadIdsWithoutFeedback() {
        return loadIds(Tb::objectId == JoinedTb::objectId && JoinedTb::feedbackTaskId == std::nullopt);
    }

    Ids loadIdsByAssignmentId(TId assignmentId) {
        return loadIds(Tb::assignmentId == assignmentId);
    }

    Entities loadByAssignmentId(TId assignmentId) {
        return load(Tb::assignmentId == assignmentId);
    }
};

} // namespace maps::mrc::db::ugc
