#include <library/cpp/geobase/lookup.hpp>
#include <maps/infra/yacare/include/params/tvm.h>
#include <maps/infra/yacare/include/yacare.h>
#include <maps/libs/cmdline/include/cmdline.h>
#include <maps/libs/log8/include/log8.h>
#include <maps/libs/road_graph/include/graph.h>
#include <maps/libs/succinct_rtree/include/rtree.h>
#include <maps/wikimap/mapspro/services/mrc/agent-proxy/yacare_servant/lib/globals.h>
#include <maps/wikimap/mapspro/services/mrc/agent-proxy/yacare_servant/lib/i18n.h>
#include <maps/wikimap/mapspro/services/mrc/agent-proxy/yacare_servant/lib/utils.h>
#include <maps/wikimap/mapspro/services/mrc/libs/config/include/config.h>
#include <maps/wikimap/mapspro/services/mrc/libs/ugc_event_logger/include/logger.h>
#include <maps/libs/common/include/environment.h>
#include <maps/libs/common/include/exception.h>
#include <chrono>

namespace {

static constexpr std::string_view APP_NAME = "agent-proxy";

} // namespace

yacare::VirtualHost vhost {
    yacare::VirtualHost::SLB  { "core-nmaps-mrc-agent-proxy" },
    yacare::VirtualHost::FQDN { "core-nmaps-mrc-agent-proxy.testing.maps.n.yandex.ru" },
};

// Service accesses to external database to process requests
static yacare::ThreadPool heavyPool("heavy", yacare::ThreadPool::CPUCOUNT(10), 4096);

YCR_SET_DEFAULT(vhost);

YCR_MAIN(argc, argv) try {
    maps::cmdline::Parser parser;

    auto configPath = parser.string("config")
        .help("path to configuration");
    auto graphFolder = parser.string("graph-folder")
        .help("graph data folder")
        .defaultValue("/var/lib/yandex/maps/ecstatic/data/yandex-maps-mrc-graph-pro");
    auto geodata6 = parser.string("geodata6")
        .help("path to geodata6 file")
        .defaultValue("/var/lib/yandex/maps/ecstatic/data/yandex-maps-geodata6/geodata6.bin");
    auto ugcEventLogPath = parser.string("ugc-event-log")
        .help("path to ugc events log")
        .defaultValue("/var/log/yandex/maps/mrc/ugc_events_yacare/ugc_events.log");

    parser.parse(argc, argv);

    INFO() << "Starting " << APP_NAME;

    auto config = maps::mrc::common::templateConfigFromCmdPath(configPath);

    switch (maps::common::getYandexEnvironment()) {
        case maps::common::Environment::Stable:
        case maps::common::Environment::Testing:
            INFO() << "Enable TVM suppport";
            config.enableTvmClient();
            break;
        default:
            break;
    }

    maps::mrc::agent_proxy::initLocalization();

    INFO() << "Loading road graph";
    const maps::road_graph::Graph roadGraph(graphFolder + "/road_graph.fb", EMappingMode::Locked);
    const maps::succinct_rtree::Rtree roadGraphRTree(graphFolder + "/rtree.fb", roadGraph, EMappingMode::Locked);
    const maps::mrc::fb::GraphReader graphCoverage{graphFolder + "/graph_coverage.fb", EMappingMode::Locked};
    const std::chrono::seconds LOG_ROTATION_PERIOD(3600);
    maps::mrc::ugc_event_logger::Logger ugcEventLogger(ugcEventLogPath, LOG_ROTATION_PERIOD);
    maps::mrc::agent_proxy::WikiEditorClient wikiEditorClient(config.externals().wikiEditorHost());

    INFO() << "Loading geobase";
    const NGeobase::TLookup geobaseLookup(geodata6);
    maps::mrc::agent_proxy::Globals::initialize(
        config,
        roadGraph,
        roadGraphRTree,
        graphCoverage,
        geobaseLookup,
        ugcEventLogger,
        wikiEditorClient,
        std::make_shared<maps::mrc::agent_proxy::Suncalc>());
    yacare::tvm::configureUserAuth(
            maps::auth::BlackboxApi(maps::auth::TvmtoolSettings()));

    yacare::tvm::ScopesPolicy scopesPolicy({"maps:mrc"});
    scopesPolicy.dryRun = true;
    yacare::tvm::setUserScopesPolicy(scopesPolicy);

    yacare::setErrorReporter(maps::mrc::agent_proxy::errorReporter);
    yacare::run();

    INFO() << "Shutting down " << APP_NAME;
    return EXIT_SUCCESS;
} catch (const maps::Exception& e) {
    std::cerr << e;
    return EXIT_FAILURE;
} catch (const std::exception& e) {
    std::cerr << e.what();
    return EXIT_FAILURE;
}
