#pragma once

#include <maps/wikimap/mapspro/services/mrc/drive/firmware_updater/libs/db/include/firmware_upload.h>
#include <maps/wikimap/mapspro/services/mrc/drive/firmware_updater/libs/db/include/firmware_upload_part.h>
#include <maps/wikimap/mapspro/services/mrc/drive/firmware_updater/libs/db/include/hardware.h>

#include <maps/libs/sql_chemistry/include/gateway.h>
#include <maps/infra/yacare/include/yacare.h>
#include <maps/infra/yacare/include/params/tvm.h>

#include <unordered_map>

namespace maps::fw_updater::storage {

struct FirmwareUploadWithParts {
    db::FirmwareUpload upload;
    std::vector<db::FirmwareUploadPart> parts;
};


void checkAcl(pqxx::transaction_base& txn,
              const auth::UserInfo& userInfo,
              const db::Hardware& hardware);


template<typename T>
auto pageOrderBy(sql_chemistry::Column<T> col, unsigned results, unsigned skip, bool asc = true)
{
    auto orderBy = sql_chemistry::orderBy(col);
    if (asc) {
        orderBy.asc();
    } else {
        orderBy.desc();
    }

    if (results) {
        orderBy.limit(results);
    }
    if (skip) {
        orderBy.offset(skip);
    }
    return orderBy;
}


template <typename Container>
db::TIds getIds(const Container& items)
{
    db::TIds ids;
    ids.reserve(items.size());
    for (const auto& item : items) {
        ids.push_back(item.id());
    }
    return ids;
}

template <typename T>
std::unordered_map<db::TId, T> moveToMap(std::vector<T> items)
{
    std::unordered_map<db::TId, T> result;
    result.reserve(items.size());
    for (auto&& item : items) {
        db::TId id = item.id();
        result.emplace(id, std::move(item));
    }
    return result;
}

template <typename Id>
void sortUnique(std::vector<Id>& ids)
{
    std::sort(ids.begin(), ids.end());
    auto it = std::unique(ids.begin(), ids.end());
    ids.erase(it, ids.end());
}

} //namespace maps::fw_updater::storage
