#include "configs/config.h"

#include "api/observers.h"
#include "api/yacare_helpers.h"

#include "background_tasks/db_monitor.h"

#include <maps/infra/yacare/include/yacare.h>
#include <maps/infra/yacare/include/run.h>
#include <yandex/maps/wiki/common/extended_xml_doc.h>
#include <maps/libs/log8/include/log8.h>

#include <filesystem>
#include <iostream>


namespace {

const std::string DEFAULT_CONFIG_PATH = "/etc/yandex/maps/wiki/services/services.xml";
const std::string CONFIG_SERVICE_NAME = "core";
const std::string CONFIG_POOL_NAME    = "editor";

std::string getCfgPath(const std::string& moduleName)
{
    size_t delimPos = moduleName.rfind('-');
    const std::string postfix = delimPos != std::string::npos
        ? ("." + moduleName.substr(delimPos+1))
        : "";

    std::string cfgPath(DEFAULT_CONFIG_PATH);
    cfgPath.insert(cfgPath.rfind('.'), postfix);
    return std::filesystem::exists(cfgPath) ? cfgPath : DEFAULT_CONFIG_PATH;
}

} // namespace


yacare::VirtualHost vhost {
    yacare::VirtualHost::SLB { "wiki-editor" }, // for monrun checks

    // for RTC nginx config
    yacare::VirtualHost::SLB { "core-nmaps-editor" },
    yacare::VirtualHost::SLB { "core-nmaps-editor-writer" },
};

YCR_SET_DEFAULT(vhost);


// The number of seconds before the shutdown to serve requests while not
// responding to /ping.
YCR_OPTIONS.shutdown().grace_period() = 10;
YCR_OPTIONS.ignore_x_forwarded_for_y() = true;

YCR_MAIN(argc, argv)
{
    try {
        const auto programName =
            std::filesystem::path(argv[0]).filename().string();

        const std::string cfgPath = argc >= 2
            ? argv[1]
            : getCfgPath(programName);
        INFO() << "USING CONFIG: " << cfgPath;
        maps::wiki::ConfigScope cfgScope(cfgPath, CONFIG_SERVICE_NAME, CONFIG_POOL_NAME);
        auto* cfg = maps::wiki::cfg();
        INFO() << "PROJECT NAME: '" << cfg->projectName()
               << "', log level: " << cfg->logLevel();
        maps::log8::setLevel(cfg->logLevel());
        cfg->onLoad();
        cfg->initThreadPools(programName);
        cfg->initValidatorModules();
        maps::wiki::initObservers();
        yacare::setErrorReporter(yacareErrorReporter);

        auto dbMonitor = maps::wiki::createDbMonitor();
        yacare::run(yacare::RunSettings{.useSystemDefaultLocale = true});
        return EXIT_SUCCESS;
    } catch (maps::Exception& e) {
        std::cerr << e << std::endl;
        return EXIT_FAILURE;
    } catch (std::exception& e) {
        std::cerr << e.what() << std::endl;
        return EXIT_FAILURE;
    }
}
