#include <balancer/kernel/cookie/domain/domain.h>
#include <library/cpp/testing/unittest/registar.h>

#include <tuple>

using namespace NSrvKernel;

Y_UNIT_TEST_SUITE(TDomainPublicSuffixTest) {
    Y_UNIT_TEST(ShortestPrivateSuffix) {
        struct TTest {
            TStringBuf Domain;
            TMaybe<TStringBuf> PrivateSuff;
            TMaybe<TStringBuf> PublicSuff;
        };

        const auto testData = std::initializer_list<TTest>{
            // checkPublicSuffix(null, null);
            {"", "", ""},
            // checkPublicSuffix('COM', null);
            {"com", "", "com"},
            // checkPublicSuffix('example.COM', 'example.com');
            {"example.com", "example.com", "com"},
            // checkPublicSuffix('WwW.example.COM', 'example.com');
            {"www.example.com", "example.com", "com"},
            // checkPublicSuffix('.com', null);
            {".com", "", "com"},
            // checkPublicSuffix('.example.com', null);
            {".example.com", "example.com", "com"},

            // Unlisted TLD.
            // checkPublicSuffix('.example', null);
            {".example", "", "example"},
            // checkPublicSuffix('example', null);
            {"example", "", "example"},
            // checkPublicSuffix('.example.example', null);
            {".example.example", "example.example", "example"},
            // checkPublicSuffix('example.example', 'example.example');
            {"example.example", "example.example", "example"},
            // checkPublicSuffix('b.example.example', 'example.example');
            {"b.example.example", "example.example", "example"},
            // checkPublicSuffix('a.b.example.example', 'example.example');
            {"a.b.example.example", "example.example", "example"},

            // Listed, but non-Internet, TLD.
            //checkPublicSuffix('local', null);
            {"local", "", "local"},
            //checkPublicSuffix('example.local', null);
            {"example.local", "example.local", "local"},
            //checkPublicSuffix('b.example.local', null);
            {"b.example.local", "example.local", "local"},
            //checkPublicSuffix('a.b.example.local', null);
            {"a.b.example.local", "example.local", "local"},

            // TLD with only 1 rule.
            // checkPublicSuffix('biz', null);
            {"biz", "", "biz"},
            // checkPublicSuffix('domain.biz', 'domain.biz');
            {"domain.biz", "domain.biz", "biz"},
            // checkPublicSuffix('b.domain.biz', 'domain.biz');
            {"b.domain.biz", "domain.biz", "biz"},
            // checkPublicSuffix('a.b.domain.biz', 'domain.biz');
            {"a.b.domain.biz", "domain.biz", "biz"},

            // TLD with some 2-level rules.
            // checkPublicSuffix('com', null);
            {"com", "", "com"},
            // checkPublicSuffix('example.com', 'example.com');
            {"example.com", "example.com", "com"},
            // checkPublicSuffix('b.example.com', 'example.com');
            {"b.example.com", "example.com", "com"},
            // checkPublicSuffix('a.b.example.com', 'example.com');
            {"a.b.example.com", "example.com", "com"},
            // checkPublicSuffix('uk.com', null);
            {"uk.com", "", "uk.com"},
            // checkPublicSuffix('example.uk.com', 'example.uk.com');
            {"example.uk.com", "example.uk.com", "uk.com"},
            // checkPublicSuffix('b.example.uk.com', 'example.uk.com');
            {"b.example.uk.com", "example.uk.com", "uk.com"},
            // checkPublicSuffix('a.b.example.uk.com', 'example.uk.com');
            {"a.b.example.uk.com", "example.uk.com", "uk.com"},
            // checkPublicSuffix('test.ac', 'test.ac');
            {"test.ac", "test.ac", "ac"},

            // TLD with only 1 (wildcard) rule.
            // checkPublicSuffix('mm', null);
            {"mm", "", "mm"},
            // checkPublicSuffix('c.mm', null);
            {"c.mm", "", "c.mm"},
            // checkPublicSuffix('b.c.mm', 'b.c.mm');
            {"b.c.mm", "b.c.mm", "c.mm"},
            // checkPublicSuffix('a.b.c.mm', 'b.c.mm');
            {"a.b.c.mm", "b.c.mm", "c.mm"},

            // More complex TLD.
            // checkPublicSuffix('jp', null);
            {"jp", "", "jp"},
            // checkPublicSuffix('test.jp', 'test.jp');
            {"test.jp", "test.jp", "jp"},
            // checkPublicSuffix('www.test.jp', 'test.jp');
            {"www.test.jp", "test.jp", "jp"},
            // checkPublicSuffix('ac.jp', null);
            {"ac.jp", "", "ac.jp"},
            // checkPublicSuffix('test.ac.jp', 'test.ac.jp');
            {"test.ac.jp", "test.ac.jp", "ac.jp"},
            // checkPublicSuffix('www.test.ac.jp', 'test.ac.jp');
            {"www.test.ac.jp", "test.ac.jp", "ac.jp"},
            // checkPublicSuffix('kyoto.jp', null);
            {"kyoto.jp", "", "kyoto.jp"},
            // checkPublicSuffix('test.kyoto.jp', 'test.kyoto.jp');
            {"test.kyoto.jp", "test.kyoto.jp", "kyoto.jp"},
            // checkPublicSuffix('ide.kyoto.jp', null);
            {"ide.kyoto.jp", "", "ide.kyoto.jp"},
            // checkPublicSuffix('b.ide.kyoto.jp', 'b.ide.kyoto.jp');
            {"b.ide.kyoto.jp", "b.ide.kyoto.jp", "ide.kyoto.jp"},
            // checkPublicSuffix('a.b.ide.kyoto.jp', 'b.ide.kyoto.jp');
            {"a.b.ide.kyoto.jp", "b.ide.kyoto.jp", "ide.kyoto.jp"},
            // checkPublicSuffix('c.kobe.jp', null);
            {"c.kobe.jp", "", "c.kobe.jp"},
            // checkPublicSuffix('b.c.kobe.jp', 'b.c.kobe.jp');
            {"b.c.kobe.jp", "b.c.kobe.jp", "c.kobe.jp"},
            // checkPublicSuffix('a.b.c.kobe.jp', 'b.c.kobe.jp');
            {"a.b.c.kobe.jp", "b.c.kobe.jp", "c.kobe.jp"},
            // checkPublicSuffix('city.kobe.jp', 'city.kobe.jp');
            {"city.kobe.jp", "city.kobe.jp", "kobe.jp"},
            // checkPublicSuffix('www.city.kobe.jp', 'city.kobe.jp');
            {"www.city.kobe.jp", "city.kobe.jp", "kobe.jp"},

            // TLD with a wildcard rule and exceptions.
            // checkPublicSuffix('ck', null);
            {"ck", "", "ck"},
            // checkPublicSuffix('test.ck', null);
            {"test.ck", "", "test.ck"},
            // checkPublicSuffix('b.test.ck', 'b.test.ck');
            {"b.test.ck", "b.test.ck", "test.ck"},
            // checkPublicSuffix('a.b.test.ck', 'b.test.ck');
            {"a.b.test.ck", "b.test.ck", "test.ck"},
            // checkPublicSuffix('www.ck', 'www.ck');
            {"www.ck", "www.ck", "ck"},
            // checkPublicSuffix('www.www.ck', 'www.ck');
            {"www.www.ck", "www.ck", "ck"},

            // US K12.
            // checkPublicSuffix('us', null);
            {"us", "", "us"},
            // checkPublicSuffix('test.us', 'test.us');
            {"test.us", "test.us", "us"},
            // checkPublicSuffix('www.test.us', 'test.us');
            {"www.test.us", "test.us", "us"},
            // checkPublicSuffix('ak.us', null);
            {"ak.us", "", "ak.us"},
            // checkPublicSuffix('test.ak.us', 'test.ak.us');
            {"test.ak.us", "test.ak.us", "ak.us"},
            // checkPublicSuffix('www.test.ak.us', 'test.ak.us');
            {"www.test.ak.us", "test.ak.us", "ak.us"},
            // checkPublicSuffix('k12.ak.us', null);
            {"k12.ak.us", "", "k12.ak.us"},
            // checkPublicSuffix('test.k12.ak.us', 'test.k12.ak.us');
            {"test.k12.ak.us", "test.k12.ak.us", "k12.ak.us"},
            // checkPublicSuffix('www.test.k12.ak.us', 'test.k12.ak.us');
            {"www.test.k12.ak.us", "test.k12.ak.us", "k12.ak.us"},

            // IDN labels.
            // NOTE: no unicode normalization performed
            // checkPublicSuffix('食狮.com.cn', '食狮.com.cn');
            {"食狮.com.cn", "食狮.com.cn", "com.cn"},
            // checkPublicSuffix('食狮.公司.cn', '食狮.公司.cn');
            {"食狮.公司.cn", "食狮.公司.cn", "公司.cn"},
            // checkPublicSuffix('www.食狮.公司.cn', '食狮.公司.cn');
            {"www.食狮.公司.cn", "食狮.公司.cn", "公司.cn"},
            // checkPublicSuffix('shishi.公司.cn', 'shishi.公司.cn');
            {"shishi.公司.cn", "shishi.公司.cn", "公司.cn"},
            // checkPublicSuffix('公司.cn', null);
            {"公司.cn", "", "公司.cn"},
            // checkPublicSuffix('食狮.中国', '食狮.中国');
            {"食狮.中国", "食狮.中国", "中国"},
            // checkPublicSuffix('www.食狮.中国', '食狮.中国');
            {"www.食狮.中国", "食狮.中国", "中国"},
            // checkPublicSuffix('shishi.中国', 'shishi.中国');
            {"shishi.中国", "shishi.中国", "中国"},
            // checkPublicSuffix('中国', null);
            {"中国", "", "中国"},

            // Same as above, but punycoded.
            // checkPublicSuffix('xn--85x722f.com.cn', 'xn--85x722f.com.cn');
            {"xn--85x722f.com.cn", "xn--85x722f.com.cn", "com.cn"},
            // checkPublicSuffix('xn--85x722f.xn--55qx5d.cn', 'xn--85x722f.xn--55qx5d.cn');
            {"xn--85x722f.xn--55qx5d.cn", "xn--85x722f.xn--55qx5d.cn", "xn--55qx5d.cn"},
            // checkPublicSuffix('www.xn--85x722f.xn--55qx5d.cn', 'xn--85x722f.xn--55qx5d.cn');
            {"www.xn--85x722f.xn--55qx5d.cn", "xn--85x722f.xn--55qx5d.cn", "xn--55qx5d.cn"},
            // checkPublicSuffix('shishi.xn--55qx5d.cn', 'shishi.xn--55qx5d.cn');
            {"shishi.xn--55qx5d.cn", "shishi.xn--55qx5d.cn", "xn--55qx5d.cn"},
            // checkPublicSuffix('xn--55qx5d.cn', null);
            {"xn--55qx5d.cn", "", "xn--55qx5d.cn"},
            // checkPublicSuffix('xn--85x722f.xn--fiqs8s', 'xn--85x722f.xn--fiqs8s');
            {"xn--85x722f.xn--fiqs8s", "xn--85x722f.xn--fiqs8s", "xn--fiqs8s"},
            // checkPublicSuffix('www.xn--85x722f.xn--fiqs8s', 'xn--85x722f.xn--fiqs8s');
            {"www.xn--85x722f.xn--fiqs8s", "xn--85x722f.xn--fiqs8s", "xn--fiqs8s"},
            // checkPublicSuffix('shishi.xn--fiqs8s', 'shishi.xn--fiqs8s');
            {"shishi.xn--fiqs8s", "shishi.xn--fiqs8s", "xn--fiqs8s"},
            // checkPublicSuffix('xn--fiqs8s', null); */
            {"xn--fiqs8s", "", "xn--fiqs8s"},

            {"yandex.market", "yandex.market", "market"},
            {"yandex.com.tr", "yandex.com.tr", "com.tr"},
            {"yandex.com.ua", "yandex.com.ua", "com.ua"},
            {"m.market.yandex.com.ua", "yandex.com.ua", "com.ua"},
            {"market.yandex", "market.yandex", "yandex"},
            {"market.yandex.", "market.yandex.", "yandex."},
            {"yandex", "", "yandex"},
            {"yandex.", "", "yandex."},
            {"localhost", "", "localhost"},

            {".", "", ""},
            {"..", Nothing(), Nothing()},
            {".a.", "", "a."},
            {".a..", Nothing(), Nothing()},
            {"..a.", Nothing(), Nothing()},
            {".a.a.", "a.a.", "a."},
            {".a..a.", Nothing(), Nothing()},
            {"\x0a", "", "\x0a"},
        };

        for (auto t : testData) {
            UNIT_ASSERT_VALUES_EQUAL_C(ShortestPrivateSuffix(t.Domain), t.PrivateSuff, t.Domain);
            UNIT_ASSERT_VALUES_EQUAL_C(LongestPublicSuffix(t.Domain), t.PublicSuff, t.Domain);
        }
    }
}
