#include <Poco/Data/Session.h>

#include <unordered_set>
#include <library/cpp/uri/http_url.h>

#include <wmconsole/legacy/util/database/queries.h>
#include <wmconsole/legacy/util/logger.h>

#include "host_info_map.h"

namespace NWebmaster {

void THostInfoMap::add_host_info(const THostInfo &info, const TUserInfoMap &user_info_map) {
    std::string scheme("");

    std::string temp_name = info.name();

    if (temp_name.find("://") == std::string::npos) {
        temp_name = "http://" + temp_name; // default scheme
    } else if (temp_name.find("https://") == 0) {
        scheme = "https://";
    }

    THttpURL parsed;

    int code = parsed.ParseAbs(
                   temp_name.c_str(),
                   THttpURL::FeaturesRobot | THttpURL::FeatureUnescapeStandard | THttpURL::FeatureEscSpace | THttpURL::FeatureEscapeUnescaped
               );

    if (code) {
        log_error << "cannot parse " << info.name();
        return; // can not parse -- do nothing
    }

    std::string host_name = scheme + parsed.PrintS(THttpURL::FlagHostPort);

    THostInfoContainer &container = operator[](host_name);
    container.array.push_back(info);

    if (!info.main_user().isNull()) {
        const TUserInfo *user = user_info_map.find_user_id(info.main_user());

        if (user != nullptr) {
            container.main_user_exists = true;
        }
    }

}

bool THostInfoMap::find_host(const std::string &host, THostInfoMap::iterator &iter, bool force_find_main_user) {
    iter = find(host);

    if (iter != end()) {
        if (force_find_main_user) {
            if (iter->second.main_user_exists) {
                return true;
            }
            return false;
        }
        return true;
    }

    return false;
}

void get_host_info_map(Poco::Data::Session &user_sess, THostInfoMap &res, const TUserInfoMap &user_info_map, TMirrorResolver::Ptr mirrorResolver) {
    std::deque<THostInfoDB> verified_hosts;
    std::set<std::string> tmp_old_wm_main_mirrors;

    queries::select(
         user_sess,
        "SELECT tbl_hosts.host_id,LCASE(name),tbl_hosts_limits.limit,xd.to_user_id "
        "FROM tbl_hosts "
        "LEFT JOIN tbl_hosts_limits ON tbl_hosts.host_id = tbl_hosts_limits.host_id "
        "INNER JOIN tbl_xmllimit_delegations xd ON tbl_hosts.host_id = xd.host_id",
         verified_hosts
    );

    queries::select(
         user_sess,
        "SELECT LCASE(name) "
        "FROM tbl_hosts "
        "INNER JOIN tbl_xmllimit_delegations xd ON tbl_hosts.host_id = xd.host_id "
        "WHERE mirror_id IS NULL",
        tmp_old_wm_main_mirrors
    );

    THostInfoMap hosts_info_map;
    std::unordered_set<std::string> old_wm_main_mirrors(tmp_old_wm_main_mirrors.begin(), tmp_old_wm_main_mirrors.end());

    log_info << "Got " << verified_hosts.size() << " verified hosts";
    for (const THostInfoDB &host_db_info : verified_hosts) {
        THostInfo host_info(host_db_info);
        if (mirrorResolver->GetMirror(host_info.name()) == host_info.name() || old_wm_main_mirrors.find(host_info.name()) != old_wm_main_mirrors.end()) {
            hosts_info_map.add_host_info(host_db_info, user_info_map);
        }
    }

    res.swap(hosts_info_map);
}

} //namespace NWebmaster
