#include <yandex/maps/wiki/unittest/config.h>

#include <library/cpp/testing/common/env.h>

#include <boost/format.hpp>

#include <fstream>

namespace fs = boost::filesystem;

namespace maps::wiki::unittest {

namespace {

const fs::path CONFIG_DIR = "libyandex-maps-wiki-unittest";

const std::string SERVICES_BASE_FILEPATH =
    ArcadiaSourceRoot() + "/maps/wikimap/mapspro/cfg/services/services-base.xml";

const std::string TEMPLATE = R"(<?xml version='1.0' encoding='utf-8'?>
<config>
    <extends>%7%</extends>
    <common>
        <databases>
            <database id="core" name="%3%">
                <write host="%1%" port="%2%" user="%4%" pass="%5%"/>
                <read host="%1%" port="%2%" user="%4%" pass="%5%"/>
                <pools nearestDC="1" failPingPeriod="5" pingPeriod="30" timeout="5">
                    <core writePoolSize="4" writePoolOverflow="6" readPoolSize="6" readPoolOverflow="9"/>
                    <editor writePoolSize="10" writePoolOverflow="15" readPoolSize="6" readPoolOverflow="9"/>
                    <social writePoolSize="2" writePoolOverflow="0" readPoolSize="3" readPoolOverflow="0"/>
                    <tasks writePoolSize="2" writePoolOverflow="0" readPoolSize="3" readPoolOverflow="0"/>
                    <grinder writePoolSize="3" writePoolOverflow="4" readPoolSize="2" readPoolOverflow="4"
                             pingPeriod="10" timeout="60" timeoutEarlyOnMasterUnavailable="0"/>
                    <dataset_explorer writePoolSize="0" writePoolOverflow="4" readPoolSize="2" readPoolOverflow="4"/>
                </pools>
            </database>
            <database id="validation" name="%3%">
                <write host="%1%" port="%2%" user="%4%" pass="%5%"/>
                <read host="%1%" port="%2%" user="%4%" pass="%5%"/>
                <pools nearestDC="1" failPingPeriod="5" pingPeriod="30" timeout="5" timeoutEarlyOnMasterUnavailable="1">
                    <editor writePoolSize="2" writePoolOverflow="1" readPoolSize="0" readPoolOverflow="0"/>
                    <tasks writePoolSize="2" writePoolOverflow="1" readPoolSize="0" readPoolOverflow="0"/>
                    <grinder writePoolSize="1" writePoolOverflow="1" readPoolSize="0" readPoolOverflow="0"
                             pingPeriod="10" timeout="60" timeoutEarlyOnMasterUnavailable="0"/>
                </pools>
            </database>
            <database id="social" name="%3%">
                <write host="%1%" port="%2%" user="%4%" pass="%5%"/>
                <read host="%1%" port="%2%" user="%4%" pass="%5%"/>
                <pools nearestDC="1" failPingPeriod="5" pingPeriod="30" timeout="5">
                    <social writePoolSize="3" writePoolOverflow="3" readPoolSize="4" readPoolOverflow="6"/>
                    <grinder writePoolSize="3" writePoolOverflow="4" readPoolSize="2" readPoolOverflow="4"
                             pingPeriod="10" timeout="60" timeoutEarlyOnMasterUnavailable="0"/>
                    <editor writePoolSize="10" writePoolOverflow="15" readPoolSize="6" readPoolOverflow="9"/>
                    <editor-tool writePoolSize="10" writePoolOverflow="5" readPoolSize="6" readPoolOverflow="9"
                             pingPeriod="10" timeout="60" timeoutEarlyOnMasterUnavailable="0"/>
                </pools>
            </database>
            <database id="long-read" name="%3%">
                <write host="%1%" port="%2%" user="%4%" pass="%5%"/>
                <read host="%1%" port="%2%" user="%4%" pass="%5%"/>
                <pools nearestDC="1" failPingPeriod="5" pingPeriod="10" timeout="60" timeoutEarlyOnMasterUnavailable="0">
                    <long-read writePoolSize="10" writePoolOverflow="5" readPoolSize="6" readPoolOverflow="9"/>
                    <editor-tool writePoolSize="10" writePoolOverflow="5" readPoolSize="6" readPoolOverflow="9"/>
                    <revisionapi writePoolSize="2" writePoolOverflow="0" readPoolSize="2" readPoolOverflow="0"/>
                    <validator writePoolSize="1" writePoolOverflow="0" readPoolSize="1" readPoolOverflow="5"/>
                    <validator.heavy writePoolSize="1" writePoolOverflow="0" readPoolSize="1" readPoolOverflow="11"/>
                    <diffalert writePoolSize="1" writePoolOverflow="12" readPoolSize="4" readPoolOverflow="8"/>
                    <export-poi writePoolSize="4" writePoolOverflow="0" readPoolSize="4" readPoolOverflow="5"/>
                    <outsource-stat writePoolSize="1" writePoolOverflow="0" readPoolSize="1" readPoolOverflow="5"/>
                    <masstransit-import writePoolSize="2" writePoolOverflow="2" readPoolSize="3" readPoolOverflow="5"/>
                </pools>
            </database>
            <database id="view-trunk" name="%3%">
                <write host="%1%" port="%2%" user="%4%" pass="%5%"/>
                <read host="%1%" port="%2%" user="%4%" pass="%5%"/>
                <pools nearestDC="1" failPingPeriod="5" pingPeriod="30" timeout="5" timeoutEarlyOnMasterUnavailable="1">
                    <editor writePoolSize="4" writePoolOverflow="6" readPoolSize="6" readPoolOverflow="9"/>
                    <editor-tool writePoolSize="10" writePoolOverflow="5" readPoolSize="6" readPoolOverflow="9"
                                 pingPeriod="10" timeout="60" timeoutEarlyOnMasterUnavailable="0"/>
                </pools>
            </database>
            <database id="view-stable" name="%3%">
                <write host="%1%" port="%2%" user="%4%" pass="%5%"/>
                <read host="%1%" port="%2%" user="%4%" pass="%5%"/>
                <pools nearestDC="1" failPingPeriod="5" pingPeriod="10" timeout="60" timeoutEarlyOnMasterUnavailable="0">
                    <editor writePoolSize="4" writePoolOverflow="14" readPoolSize="3" readPoolOverflow="12"
                            pingPeriod="30" timeout="5" timeoutEarlyOnMasterUnavailable="1"/>
                    <editor-tool writePoolSize="10" writePoolOverflow="5" readPoolSize="6" readPoolOverflow="9"/>
                    <diffalert writePoolSize="1" writePoolOverflow="12" readPoolSize="4" readPoolOverflow="8"/>
                </pools>
            </database>
        </databases>
    </common>
    %6%
</config>)";

} // namespace

//=================================================================

ConfigFileHolder::ConfigFileHolder(
    const std::string& host,
    uint64_t port,
    const std::string& dbname,
    const std::string& user,
    const std::string& password,
    const std::string& services,
    const std::string& extend)
{
    auto config = boost::format(TEMPLATE)
        % host
        % port
        % dbname
        % user
        % password
        % services
        % (extend.empty() ? SERVICES_BASE_FILEPATH : extend);

    auto dir = fs::temp_directory_path() / CONFIG_DIR;
    if (!fs::exists(dir)) {
        fs::create_directories(dir);
        fs::permissions(dir, fs::all_all);
    }
    filepath_ = dir / fs::unique_path().replace_extension("xml");

    std::ofstream file(filepath_.string(), std::ios::out);
    file << config.str();
    file.close();
}

ConfigFileHolder::ConfigFileHolder(
        const local_postgres::Database& database,
        const std::string& services,
        const std::string& extend)
    : ConfigFileHolder(
        database.host(),
        database.port(),
        database.dbname(),
        database.user(),
        database.password(),
        services,
        extend)
{
}

ConfigFileHolder::~ConfigFileHolder()
{
    fs::remove(filepath_);
}

} // maps::wiki::unittest
