#pragma once

#include "yt_panorama_loader.h"

#include <maps/libs/chrono/include/time_point.h>
#include <maps/libs/pgpool3utils/include/yandex/maps/pgpool3utils/pg_advisory_mutex.h>
#include <maps/wikimap/mapspro/services/mrc/libs/config/include/config.h>

namespace maps::mrc::eye {

// Panoramas importer from YT tables to MRC DB.
// https://yt.yandex-team.ru/hahn/navigation?path=//home/maps/streetview/stable/release

class YtPanoramaImporter {
public:
    struct Metadata {
        chrono::TimePoint updatedAt;
        std::uint64_t panoramaRevision;
    };

    YtPanoramaImporter(
        const common::Config& mrcConfig,
        NYT::IClientPtr ytClient,
        bool commit = false);

    // Try to aquire a global exclusive lock so only one instance can do the
    // job. Returns false if the lock is already taken and true othewise.
    [[nodiscard]] bool lockDB();

    // Import all panoramas at the first start and import new ones during
    // consequent runs. Detect deleted panoramas and mark them in MRC DB.
    bool import(
        chrono::TimePoint updatedAt = maps::chrono::TimePoint::clock::now());

    static std::optional<Metadata> loadMetadataFromDb(
        pgpool3::TransactionHandle& txn);

    YtPanoramaLoader& ytPanoramaLoader();

private:
    struct Update {
        PanoramaDescriptions panoramaDescriptions;
        std::vector<std::string> deletedOIDs;
    };

    std::vector<std::string> loadSortedExistingOIDs();

    Update getUpdate(PanoramaDescriptions panoramaDescriptions);

    void updateMetadata(
        pgpool3::TransactionHandle& txn,
        std::uint64_t panoramaRevision,
        chrono::TimePoint updatedAt);

    void updateMetadata(
        const std::uint64_t panoramaRevision, chrono::TimePoint updatedAt);

    // WARN: The next three members initialization depends on the order they
    //       are declared in. Don't change it!
    common::Config mrcConfig_;
    wiki::common::PoolHolder pgPoolHolder_;
    pgp3utils::PgAdvisoryXactMutex pgMutex_;

    YtPanoramaLoader ytPanoramaLoader_;
    bool commit_{false};
};

} // namespace maps::mrc::eye
