#include "secret_key.h"
#include <saas/deploy_manager/modules/resources/resources.h>
#include <saas/deploy_manager/server/client/client.h>
#include <saas/deploy_manager/meta/cluster.h>
#include <saas/indexerproxy/configs/config.h>
#include <library/cpp/digest/md5/md5.h>
#include <library/cpp/json/json_writer.h>

namespace NRTYDeploy {

    void TScriptSecretKey::BuildReportForName(const TString& serviceName) {
        NJson::TJsonValue jsonService;
        bool keyFind = false;
        for (ui32 i = 0; i < Secrets.size(); ++i) {
            if (!!DecodedMD5) {
                if (DecodedMD5 == MD5::Calc(serviceName + " " + Secrets[i])) {
                    jsonService.InsertValue("adapter", Adapters[i]);
                    keyFind = true;
                }
            } else {
                if (serviceName == Service || !Service || Service == "*") {
                    jsonService.InsertValue(Adapters[i], MD5::Calc(serviceName + " " + Secrets[i]));
                    keyFind = true;
                }
            }
        }
        if (keyFind)
            Report.InsertValue(serviceName, std::move(jsonService));
    }

    void TScriptSecretKey::OnMetaService(const NSearchMapParser::TMetaService& info) {
        BuildReportForName(info.Name);
    }

    bool TScriptSecretKey::OnService(const NSearchMapParser::TSearchMapService& service) {
        BuildReportForName(service.Name);
        return false;
    }

    bool TScriptSecretKey::Process(IDeployInfoRequest& request) {
        Service = request.GetRD().CgiParam.Get("service");
        DecodedMD5 = request.GetRD().CgiParam.Get("key");
        bool force = request.GetRD().CgiParam.Has("force") && FromString<bool>(request.GetRD().CgiParam.Get("force"));

        TString configText;
        if (!request.GetStorage().GetValue("/configs/indexerproxy/indexerproxy.conf", configText)) {
            request.Output() << "HTTP/1.1 500 \r\n\r\n";
            request.Output() << "Can't find indexerproxy config";
            return false;
        }

        try {

            TAnyYandexConfig Impl;
            if (!Impl.ParseMemory(configText.data())) {
                request.Output() << "HTTP/1.1 500 \r\n\r\n";
                request.Output() << "Incorrect indexer proxy config";
                return false;
            }

            TYandexConfig::Section* proxySection = Impl.GetFirstChild("Proxy");
            TYandexConfig::TSectionsMap sections = proxySection->GetAllChildren();
            for (TYandexConfig::TSectionsMap::const_iterator iter = sections.find("Adapter");
                iter != sections.end() && iter->first == "Adapter"; ++iter) {
                    TString adapterName, secretCode;
                    if (iter->second->GetDirectives().GetValue("Name", adapterName))
                        Adapters.push_back(adapterName);
                    if (iter->second->GetDirectives().GetValue("SecretCode", secretCode))
                        Secrets.push_back(secretCode);
            }

            const TVector<TString>& ctypes = request.GetResourcesManager().GetCTypes();
            NJson::TJsonValue json;
            for (ui32 i = 0; i < ctypes.size(); ++i) {
                const TString& currentCType = ctypes[i];
                Report = NJson::TJsonValue(NJson::JSON_MAP);
                if (force)
                    BuildReportForName(Service);
                else {
                    const NSaas::TClusterConst* clusterPtr = NSaas::TClusterLocker::DefineConst(request.GetCommonData(), currentCType);
                    const NSearchMapParser::TSearchMap& ism = clusterPtr->IPSearchMap();
                    ism.Scan(*this);
                }
                json.InsertValue(currentCType, std::move(Report));
            }
            if (json.GetMap().empty()) {
                request.Output() << "HTTP/1.1 404 \r\n\r\n";
            } else {
                request.Output() << "HTTP/1.1 200 \r\n\r\n";
                request.Output() << NJson::WriteJson(json);
            }
            return true;
        } catch (yexception& e) {
            request.Output() << "HTTP/1.1 500 \r\n\r\n";
            request.Output() << e.what();
        }

        return true;
    }

    IScript::TFactory::TRegistrator<TScriptSecretKey> TScriptSecretKey::Registrator("secret_key");
}
