#include "query_data_trie.h"

#include <library/cpp/testing/unittest/registar.h>

#include <algorithm>

using namespace NProxyMeta;

namespace {
    TSet<TString> GetAllCgiValues(const TCgiParameters& cgi, TStringBuf key) {
        const auto r = cgi.Range(key);
        return TSet<TString>(r.begin(), r.end());
    }
}

Y_UNIT_TEST_SUITE(TestFakeRequestSender) {
    Y_UNIT_TEST(TestCgiRewriting) {
        NQueryDataSaaS::TSaaSRequestRec::TRef saasRequestRecRef;
        TCgiParameters cgi;

        TFakeRequestSender sender(saasRequestRecRef, cgi);

        NQueryDataSaaS::TSaasKey saasKey;
        saasKey.Key.SetKeyPrefix(1);
        saasKey.Key.SetMainKey("mainKey");

        NQueryDataSaaS::TSaaSRequestRec::TRef requestContextRef = new NQueryDataSaaS::TSaaSRequestRec();
        TString additionalCgiParams = "&gta=QDSaaS%3Ans1&gta=QDSaaS%3Ans2&gta=QDSaaS%3Ans3";
        sender.SendRequest("", saasKey, requestContextRef, additionalCgiParams);

        UNIT_ASSERT_EQUAL(requestContextRef.Get(), saasRequestRecRef.Get());
        UNIT_ASSERT_EQUAL(cgi.Print(), "gta=QDSaaS%3Ans1&gta=QDSaaS%3Ans2&gta=QDSaaS%3Ans3&text=CAESB21haW5LZXk.");
    }
}

Y_UNIT_TEST_SUITE(TQueryDataTrieRearrange) {
    void ValidateKeyTypeEntry(const NJson::TJsonValue& ktJson, const bool disable, const bool lastUnique) {
        UNIT_ASSERT_EQUAL((bool)ktJson["Disable"].GetUInteger(), disable);
        UNIT_ASSERT_EQUAL((bool)ktJson["LastUnique"].GetUInteger(), lastUnique);
    }

    Y_UNIT_TEST(TestParamsProcessing) {
        TCustomRearrangeParams params;
        params.Parameters["DefaultKps"] = "1";
        params.Parameters["SaaSType"] = "Trie";
        params.Parameters["OptimizeKeyTypes"] = "true";
        params.Parameters["KT_QueryStrong"] = "false,false";
        params.Parameters["KT_QueryDoppel"] = "false,false";
        params.Parameters["KT_QueryDoppelToken"] = "false,false";
        params.Parameters["KT_QueryDoppelPair"] = "false,false";
        params.Parameters["KT_UserId"] = "false,false";
        params.Parameters["KT_StructKey"] = "false,false";
        ICustomRearrangeFactory::TPtr ruleFactoryPtr{ICustomRearrangeFactory::TFactory::Construct("QueryDataTrie", params)};
        ICustomRearrange::TPtr rule = ruleFactoryPtr->CreateRerrangeInstance();
        const TString strConfig = ((TQueryDataTrieRearrange*)rule.Get())->GetConfig();
        NJson::TJsonValue result;
        UNIT_ASSERT(NJson::ReadJsonFastTree(strConfig, &result));
        UNIT_ASSERT(result.IsMap());
        UNIT_ASSERT_EQUAL(result["DefaultKps"].GetUInteger(), 1);
        UNIT_ASSERT_EQUAL(result["MaxKeysInRequest"].GetUInteger(), Max<ui32>());
        UNIT_ASSERT_EQUAL(result["MaxRequests"].GetUInteger(), 1);
        UNIT_ASSERT_EQUAL(result["OptimizeKeyTypes"].GetUInteger(), 1);
        UNIT_ASSERT_EQUAL(result["SaaSType"].GetString(), "Trie");

        const NJson::TJsonValue& keyTypes = result["KeyTypes"];
        ValidateKeyTypeEntry(keyTypes["QueryDoppel"], false, false);
        ValidateKeyTypeEntry(keyTypes["QueryDoppelToken"], false, false);
        ValidateKeyTypeEntry(keyTypes["QueryDoppelPair"], false, false);
        ValidateKeyTypeEntry(keyTypes["QueryStrong"], false, false);
        ValidateKeyTypeEntry(keyTypes["UserId"], false, false);
        ValidateKeyTypeEntry(keyTypes["StructKey"], false, false);
    }

    Y_UNIT_TEST(TestDefaultKps) {
        TCustomRearrangeParams params;
        params.Parameters["SaaSType"] = "Trie";
        params.Parameters["OptimizeKeyTypes"] = "true";
        params.Parameters["KT_QueryStrong"] = "false,false";
        ICustomRearrangeFactory::TPtr ruleFactoryPtr{ICustomRearrangeFactory::TFactory::Construct("QueryDataTrie", params)};
        ICustomRearrange::TPtr rule = ruleFactoryPtr->CreateRerrangeInstance();
        const TString strConfig = ((TQueryDataTrieRearrange*)rule.Get())->GetConfig();
        NJson::TJsonValue result;
        UNIT_ASSERT(NJson::ReadJsonFastTree(strConfig, &result));
        UNIT_ASSERT(result.IsMap());
        UNIT_ASSERT_EQUAL(result["DefaultKps"].GetUInteger(), 0);
        UNIT_ASSERT_EQUAL(result["MaxKeysInRequest"].GetUInteger(), Max<ui32>());
        UNIT_ASSERT_EQUAL(result["MaxRequests"].GetUInteger(), 1);
        UNIT_ASSERT_EQUAL(result["OptimizeKeyTypes"].GetUInteger(), 1);
        UNIT_ASSERT_EQUAL(result["SaaSType"].GetString(), "Trie");

        const NJson::TJsonValue& keyTypes = result["KeyTypes"];
        ValidateKeyTypeEntry(keyTypes["QueryStrong"], false, false);
    }

    Y_UNIT_TEST(TestFormParams) {
        TCustomRearrangeParams params;
        params.Parameters["SaaSType"] = "Trie";
        params.Parameters["OptimizeKeyTypes"] = "false";
        params.Parameters["KT_QueryStrong"] = "false,false";
        params.Parameters["KT_QueryDoppel"] = "false,false";
        params.Parameters["KT_StructKey"] = "false,false";
        params.Parameters["KT_StructKey-UserRegion"] = "false,false";
        ICustomRearrangeFactory::TPtr ruleFactoryPtr{ICustomRearrangeFactory::TFactory::Construct("QueryDataTrie", params)};
        ICustomRearrange::TPtr rule = ruleFactoryPtr->CreateRerrangeInstance();

        TCgiParameters cgi;
        cgi.InsertUnescaped("text", "request text");
        cgi.InsertUnescaped("rearr",
            "device=desktop;is_mobile=0;all_regions=213,1,3,225,10001,10000;urcntr=225,10001,10000;gsmop=0;"
            "qd_struct_keys={"
                "blender_wc_norm_bigram:{\"request text\":null,\"request text\":null},"
                "default_search:{punto_switcher_teaser:1},"
                "facts:{\"request text\":null},"
                "mediaportraits_serp:{ruw135151:null},"
                "new_daily_pairs:{\"request text\":null,\"request text\":null},"
                "quick_pair:{\"request text\":null,\"request text\":null},"
                "video_series_struct:{\"\":null},"
                "weatherdata:{\"l:ru|u:logged|questions\":1},"
                "wiz_video_factors:{\"request text\":null}"
            "};"
        );
        cgi.InsertUnescaped("relev", "uil=ru;norm=request text;dnorm=request text;dnorm_w=request text;");
        rule->FormCgiParams(cgi, nullptr);

        UNIT_ASSERT_EQUAL(cgi.Get("comp_search"), "comp:TRIE;max_docs:100500;key_type:complex_key");
        UNIT_ASSERT_EQUAL(cgi.Get("component"), "TRIE");
        TSet<TString> texts;
        texts.insert("EgIuMRoBMSISCgExEg0JcmVxdWVzdCB0ZXh0");
        texts.insert("EgIuMhoBMiISCgEyEg0JcmVxdWVzdCB0ZXh0");
        texts.insert("EgIuNhoBNiKFAgoBNhIkCWJsZW5kZXJfd2Nfbm9ybV9iaWdyYW1AcmVxdWVzdCB0ZXh0EiUJZGVmYXVsdF9zZWFyY2hAcHVudG9fc3dpdGNoZXJfdGVhc2VyEhMJZmFjdHNAcmVxdWVzdCB0ZXh0Eh4JbWVkaWFwb3J0cmFpdHNfc2VycEBydXcxMzUxNTESHQluZXdfZGFpbHlfcGFpcnNAcmVxdWVzdCB0ZXh0EhgJcXVpY2tfcGFpckByZXF1ZXN0IHRleHQSJAl3ZWF0aGVyZGF0YUBsOnJ1fHU6bG9nZ2VkfHF1ZXN0aW9ucxIfCXdpel92aWRlb19mYWN0b3JzQHJlcXVlc3QgdGV4dA..");
        texts.insert("EgQuNi41GgE2GgE1IoUCCgE2EiQJYmxlbmRlcl93Y19ub3JtX2JpZ3JhbUByZXF1ZXN0IHRleHQSJQlkZWZhdWx0X3NlYXJjaEBwdW50b19zd2l0Y2hlcl90ZWFzZXISEwlmYWN0c0ByZXF1ZXN0IHRleHQSHgltZWRpYXBvcnRyYWl0c19zZXJwQHJ1dzEzNTE1MRIdCW5ld19kYWlseV9wYWlyc0ByZXF1ZXN0IHRleHQSGAlxdWlja19wYWlyQHJlcXVlc3QgdGV4dBIkCXdlYXRoZXJkYXRhQGw6cnV8dTpsb2dnZWR8cXVlc3Rpb25zEh8Jd2l6X3ZpZGVvX2ZhY3RvcnNAcmVxdWVzdCB0ZXh0IisKATUSBAkyMTMSAgkxEgIJMxIECTIyNRIGCTEwMDAxEgYJMTAwMDASAgkw");

        UNIT_ASSERT_EQUAL(cgi.NumOfValues("text"), texts.size());
        UNIT_ASSERT_EQUAL(GetAllCgiValues(cgi, "text"), texts);
    }

    Y_UNIT_TEST(TestFormParams2) {
        TCustomRearrangeParams params;
        params.Parameters["SaaSType"] = "Trie";
        params.Parameters["OptimizeKeyTypes"] = "false";
        params.Parameters["KT_QueryStrong"] = "false,false";
        params.Parameters["KT_QueryDoppel"] = "false,false";
        params.Parameters["KT_QueryDoppelToken"] = "false,false";
        params.Parameters["KT_QueryDoppelPair"] = "false,false";
        params.Parameters["KT_StructKey"] = "false,false";
        params.Parameters["KT_StructKey-UserRegion"] = "false,false";
        ICustomRearrangeFactory::TPtr ruleFactoryPtr{ICustomRearrangeFactory::TFactory::Construct("QueryDataTrie", params)};
        ICustomRearrange::TPtr rule = ruleFactoryPtr->CreateRerrangeInstance();

        TCgiParameters cgi;
        cgi.InsertUnescaped("text", "tok1 tok2 tok3");
        cgi.InsertUnescaped("rearr",
            "device=desktop;is_mobile=0;all_regions=213,1,3,225,10001,10000;urcntr=225,10001,10000;gsmop=0;"
            "qd_struct_keys={"
                "blender_wc_norm_bigram:{\"tok1 tok2 tok3\":null,\"tok1 tok2 tok3\":null},"
                "default_search:{punto_switcher_teaser:1},facts:{\"tok1 tok2 tok3\":null},"
                "mediaportraits_serp:{ruw135151:null},"
                "new_daily_pairs:{\"tok1 tok2\":null,\"tok2 tok3\":null},"
                "quick_pair:{\"tok1 tok2\":null,\"tok2 tok3\":null},"
                "video_series_struct:{\"\":null},"
                "weatherdata:{\"l:ru|u:logged|questions\":1},"
                "wiz_video_factors:{\"tok1 tok2 tok3\":null}"
            "};"
        );
        cgi.InsertUnescaped("relev", "uil=ru;norm=tok1 tok2 tok3;dnorm=tok1 tok2 tok3;dnorm_w=tok1 tok2 tok3;");
        rule->FormCgiParams(cgi, nullptr);

        UNIT_ASSERT_EQUAL(cgi.Get("comp_search"), "comp:TRIE;max_docs:100500;key_type:complex_key");
        UNIT_ASSERT_EQUAL(cgi.Get("component"), "TRIE");
        TSet<TString> texts;
        texts.insert("EgIuMRoBMSIUCgExEg8JdG9rMSB0b2syIHRvazM.");
        texts.insert("EgIuMhoBMiIUCgEyEg8JdG9rMSB0b2syIHRvazM.");
        texts.insert("EgIuNhoBNiK4AgoBNhImCWJsZW5kZXJfd2Nfbm9ybV9iaWdyYW1AdG9rMSB0b2syIHRvazMSJQlkZWZhdWx0X3NlYXJjaEBwdW50b19zd2l0Y2hlcl90ZWFzZXISFQlmYWN0c0B0b2sxIHRvazIgdG9rMxIeCW1lZGlhcG9ydHJhaXRzX3NlcnBAcnV3MTM1MTUxEhoJbmV3X2RhaWx5X3BhaXJzQHRvazEgdG9rMhIaCW5ld19kYWlseV9wYWlyc0B0b2syIHRvazMSFQlxdWlja19wYWlyQHRvazEgdG9rMhIVCXF1aWNrX3BhaXJAdG9rMiB0b2szEiQJd2VhdGhlcmRhdGFAbDpydXx1OmxvZ2dlZHxxdWVzdGlvbnMSIQl3aXpfdmlkZW9fZmFjdG9yc0B0b2sxIHRvazIgdG9rMw..");
        texts.insert("EgMuMTEaAjExIhkKAjExEgUJdG9rMRIFCXRvazISBQl0b2sz");
        texts.insert("EgMuMTIaAjEyIj0KAjEyEgoJdG9rMSB0b2syEgoJdG9rMSB0b2szEgUJdG9rMRIKCXRvazIgdG9rMxIFCXRvazISBQl0b2sz");
        texts.insert("EgQuNi41GgE2GgE1IrgCCgE2EiYJYmxlbmRlcl93Y19ub3JtX2JpZ3JhbUB0b2sxIHRvazIgdG9rMxIlCWRlZmF1bHRfc2VhcmNoQHB1bnRvX3N3aXRjaGVyX3RlYXNlchIVCWZhY3RzQHRvazEgdG9rMiB0b2szEh4JbWVkaWFwb3J0cmFpdHNfc2VycEBydXcxMzUxNTESGgluZXdfZGFpbHlfcGFpcnNAdG9rMSB0b2syEhoJbmV3X2RhaWx5X3BhaXJzQHRvazIgdG9rMxIVCXF1aWNrX3BhaXJAdG9rMSB0b2syEhUJcXVpY2tfcGFpckB0b2syIHRvazMSJAl3ZWF0aGVyZGF0YUBsOnJ1fHU6bG9nZ2VkfHF1ZXN0aW9ucxIhCXdpel92aWRlb19mYWN0b3JzQHRvazEgdG9rMiB0b2szIisKATUSBAkyMTMSAgkxEgIJMxIECTIyNRIGCTEwMDAxEgYJMTAwMDASAgkw");

        UNIT_ASSERT_EQUAL(cgi.NumOfValues("text"), texts.size());
        UNIT_ASSERT_EQUAL(GetAllCgiValues(cgi, "text"), texts);
    }

}


