#pragma once

#include "common.h"
#include "loader_helpers.h"
#include "poi_def.h"
#include <maps/libs/pgpool/include/pgpool3.h>
#include <maps/wikimap/mapspro/libs/poi_feed/include/helpers.h>

#include <yandex/maps/wiki/revision/revisionid.h>
#include <yandex/maps/wiki/revision/snapshot.h>

#include <pqxx/pqxx>

#include <functional>
#include <unordered_map>
#include <unordered_set>

namespace maps::wiki::poi {

struct CommitData {
    DBID id;
    chrono::TimePoint time;
    UserID author;
};

using FtTypeIdSet = std::unordered_set<FtTypeId>;
using PoiIdToDefMap = std::unordered_map<DBID, PoiDef>;
using PoiIdToEntranceDefMap = std::unordered_map<DBID, EntranceDef>;
using ObjectIdCommitDataFunctor = std::function<CommitData(DBID)>;
using ObjectIdToPermalinkUnknownMap = std::unordered_map<DBID, DBID>;

class Loader {
public:
    Loader(pqxx::transaction_base& yMapsDf,
           pgpool3::Pool& socialPool,
           revision::Snapshot& tds,
           const FtTypeIdToRubricIdMultimap& mapping,
           const FtTypeIdToRubricIdMultimap& parentMapping,
           ObjectIdToPermalinkUnknownMap&& nyakMappingUnknownPermalinks);

    DBIDSet loadPoiIds();
    PoiDefs loadPoiDefs(const DBIDSet& poiIds);

private:
    pqxx::transaction_base& yMapsDf_;
    pgpool3::Pool& socialPool_;
    revision::Snapshot& tds_;
    const FtTypeIdToRubricIdMultimap& mapping_;
    const FtTypeIdToRubricIdMultimap& parentMapping_;
    const ObjectIdToPermalinkUnknownMap nyakMappingUnknownPermalinks_;

    FtTypeIdSet getFtTypeIds() const;

    void loadFtData(PoiIdToDefMap& poiIdToDefMap);
    void loadRubrics(PoiIdToDefMap& poiIdToDefMap);

    void loadNames(PoiIdToDefMap& poiIdToDefMap);

    void loadGeoms(PoiIdToDefMap& poiIdToDefMap);

    void loadAttrs(PoiIdToDefMap& poiIdToDefMap);

    void loadEntrances(PoiIdToDefMap& poiIdToDefMap);

    revision::RevisionIds loadRevisionIds(const PoiIdToDefMap& poiIdToDefMap);
    void updateWithRecentSlaveRevisions(const PoiIdToDefMap& poiIdToDefMap, ObjectIdToCommitIdMap&);

    ObjectIdCommitDataFunctor
    loadObjectCommitDatas(const revision::RevisionIds& revIds, const PoiIdToDefMap& poiIdToDefMap);

    void loadActualizationDate(PoiIdToDefMap& poiIdToDefMap);
    void resetReservedPermalinkForRealAssigned(const PoiIdToDefMap& poiIdToDefMap);
    void trySetPermalinkFromUnknown(PoiIdToDefMap& poiIdToDefMap);
    void setPermalinkFromReserve(PoiIdToDefMap& poiIdToDefMap);
};

} // namespace maps::wiki::poi
