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

#include <balancer/drlogger_nel/library/configuration.h>


namespace {
    void AssertSiteRegexp(
        const TTenantConfiguration tenantConfiguration,
        const TString request,
        const TString site,
        const bool shouldMatch
    ) {
        auto [acceptedIt, acceptedEnd] = tenantConfiguration.SitesRegex.AcceptedRegexps(
            NPire::Runner(tenantConfiguration.SitesRegex).Run(request).State()
        );

        bool matchedSite = false;
        for (; acceptedIt < acceptedEnd && !matchedSite; ++acceptedIt) {
            matchedSite |= !tenantConfiguration.Sites[*acceptedIt].compare(site);
        }
        UNIT_ASSERT(matchedSite == shouldMatch);
    }
};


Y_UNIT_TEST_SUITE(TConfigurationTest) {
    
    Y_UNIT_TEST(SimpleValidConfig) {
        TConfiguration configuration;
        UNIT_ASSERT(configuration.ReadFromYAMLString(NResource::Find("config.yaml")));

        UNIT_ASSERT_VALUES_EQUAL(configuration.NELPort, 80);
        UNIT_ASSERT_STRINGS_EQUAL(configuration.AccessLogFilePath, "log.txt");

        UNIT_ASSERT_VALUES_EQUAL(configuration.MaxReportAge, TDuration::Seconds(120));

        UNIT_ASSERT_VALUES_EQUAL(configuration.Tenants.size(), 1);
        UNIT_ASSERT(configuration.Tenants.contains("yandex"));
        
        UNIT_ASSERT_VALUES_EQUAL(configuration.Tenants["yandex"].ASNs->size(), 3);
        UNIT_ASSERT(configuration.Tenants["yandex"].ASNs->contains("AS123"));
    }

    Y_UNIT_TEST(SiteRegexpWithoutSubpaths) {
        TConfiguration configuration;
        UNIT_ASSERT(configuration.ReadFromYAMLString(NResource::Find("config.yaml")));

        AssertSiteRegexp(configuration.Tenants["yandex"], "yandex.ru",         "yandex_ru_without_subpaths", true);
        AssertSiteRegexp(configuration.Tenants["yandex"], "yandex!ru",         "yandex_ru_without_subpaths", false);
        AssertSiteRegexp(configuration.Tenants["yandex"], "yandex.ru/weather", "yandex_ru_without_subpaths", false);
    }

    Y_UNIT_TEST(SiteRegexpWithSubpaths) {
        TConfiguration configuration;
        UNIT_ASSERT(configuration.ReadFromYAMLString(NResource::Find("config.yaml")));

        AssertSiteRegexp(configuration.Tenants["yandex"], "yandex.ru",         "yandex_ru_with_subpaths", true);
        AssertSiteRegexp(configuration.Tenants["yandex"], "yandex.ru/weather", "yandex_ru_with_subpaths", true);
    }

    Y_UNIT_TEST(SiteRegexpUnscreenedDot) {
        TConfiguration configuration;
        UNIT_ASSERT(configuration.ReadFromYAMLString(NResource::Find("config.yaml")));

        AssertSiteRegexp(configuration.Tenants["yandex"], "yandex.ru", "yandex_ru_unscreened_dot", true);
        AssertSiteRegexp(configuration.Tenants["yandex"], "yandex!ru", "yandex_ru_unscreened_dot", true);
    }

    Y_UNIT_TEST(SiteRegexpRuComNetSingleRegexp) {
        TConfiguration configuration;
        UNIT_ASSERT(configuration.ReadFromYAMLString(NResource::Find("config.yaml")));

        AssertSiteRegexp(configuration.Tenants["yandex"], "yandex.ru",  "yandex_ru_com_net_single_regexp", true);
        AssertSiteRegexp(configuration.Tenants["yandex"], "yandex.com", "yandex_ru_com_net_single_regexp", true);
        AssertSiteRegexp(configuration.Tenants["yandex"], "yandex.net", "yandex_ru_com_net_single_regexp", true);
        AssertSiteRegexp(configuration.Tenants["yandex"], "yandex.by",  "yandex_ru_com_net_single_regexp", false);
    }

    Y_UNIT_TEST(SiteRegexpRuComNetSeveralRegexps) {
        TConfiguration configuration;
        UNIT_ASSERT(configuration.ReadFromYAMLString(NResource::Find("config.yaml")));

        AssertSiteRegexp(configuration.Tenants["yandex"], "yandex.ru",  "yandex_ru_com_net_several_regexps", true);
        AssertSiteRegexp(configuration.Tenants["yandex"], "yandex.com", "yandex_ru_com_net_several_regexps", true);
        AssertSiteRegexp(configuration.Tenants["yandex"], "yandex.net", "yandex_ru_com_net_several_regexps", true);
        AssertSiteRegexp(configuration.Tenants["yandex"], "yandex.by",  "yandex_ru_com_net_several_regexps", false);
    }

    Y_UNIT_TEST(SiteRegexpWeather) {
        TConfiguration configuration;
        UNIT_ASSERT(configuration.ReadFromYAMLString(NResource::Find("config.yaml")));

        AssertSiteRegexp(configuration.Tenants["yandex"], "yandex.ru",            "weather", false);
        AssertSiteRegexp(configuration.Tenants["yandex"], "yandex.ru/weather",    "weather", true);
        AssertSiteRegexp(configuration.Tenants["yandex"], "yandex.ru/pogoda",     "weather", true);
        AssertSiteRegexp(configuration.Tenants["yandex"], "yandex.ru/weather/hi", "weather", true);
    }

    Y_UNIT_TEST(NonExistentFile) {
        TConfiguration configuration;
        UNIT_ASSERT(!configuration.ReadFromYAMLFile("non existent file"));
    }

    Y_UNIT_TEST(WrongConfigFieldType) {
        const TString invalidConfigFilePath = "bye";

        TConfiguration configuration;
        UNIT_ASSERT(!configuration.ReadFromYAMLString(NResource::Find("invalid_config.yaml")));
    }

}

