// Copyright 2026 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/enterprise/browser/reporting/pref_url_list_matcher.h"

#include <memory>

#include "base/values.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/testing_pref_service.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"

namespace enterprise_reporting {

const char kTestPref[] = "test.pref.name";

class PrefURLListMatcherTest : public ::testing::Test {
 protected:
  PrefURLListMatcherTest() = default;
  ~PrefURLListMatcherTest() override = default;

  void SetUp() override {
    pref_service_.registry()->RegisterListPref(kTestPref);
  }

  void SetPref(const std::vector<std::string>& urls) {
    base::ListValue urlList;
    for (const auto& url : urls) {
      urlList.Append(base::Value(url));
    }
    pref_service_.SetList(kTestPref, std::move(urlList));
  }

  TestingPrefServiceSimple pref_service_;
};

TEST_F(PrefURLListMatcherTest, Match) {
  PrefURLListMatcher matcher(&pref_service_, kTestPref);
  SetPref({"www.example.com"});
  EXPECT_EQ("www.example.com",
            *matcher.GetMatchedURL(GURL("https://www.example.com")));
  EXPECT_EQ("www.example.com",
            *matcher.GetMatchedURL(GURL("https://www.example.com/")));
  EXPECT_EQ("www.example.com",
            *matcher.GetMatchedURL(GURL("http://www.example.com/path")));
  EXPECT_EQ("www.example.com",
            *matcher.GetMatchedURL(GURL("https://www.example.com/path")));
  EXPECT_EQ("www.example.com",
            *matcher.GetMatchedURL(GURL("https://www.example.com:8088/path")));
  EXPECT_EQ(
      "www.example.com",
      *matcher.GetMatchedURL(GURL("https://www.example.com/path?query=text")));
}

TEST_F(PrefURLListMatcherTest, NotMatch) {
  PrefURLListMatcher matcher(&pref_service_, kTestPref);
  SetPref({"www.example.com"});
  EXPECT_FALSE(matcher.GetMatchedURL(GURL("https://www.example2.com")));
  EXPECT_FALSE(matcher.GetMatchedURL(GURL("https://example.com")));
  EXPECT_FALSE(matcher.GetMatchedURL(GURL("https://chat.example2.com")));
}

TEST_F(PrefURLListMatcherTest, SubDomain) {
  PrefURLListMatcher matcher(&pref_service_, kTestPref);
  SetPref({"www.example.com", "example2.com", ".example3.com"});

  // Only subdomain www is matched
  EXPECT_FALSE(matcher.GetMatchedURL(GURL("https://example.com")));
  EXPECT_FALSE(matcher.GetMatchedURL(GURL("https://chat.example.com")));
  EXPECT_TRUE(matcher.GetMatchedURL(GURL("https://www.example.com")));

  // All subdomains are matched.
  EXPECT_TRUE(matcher.GetMatchedURL(GURL("https://example2.com")));
  EXPECT_TRUE(matcher.GetMatchedURL(GURL("https://chat.example2.com")));
  EXPECT_TRUE(matcher.GetMatchedURL(GURL("https://www.example2.com")));
  EXPECT_TRUE(matcher.GetMatchedURL(GURL("https://s1.s2.example2.com")));

  // Subdomain wildcard matching is disabled with prefix dot.
  EXPECT_TRUE(matcher.GetMatchedURL(GURL("https://example3.com")));
  EXPECT_FALSE(matcher.GetMatchedURL(GURL("https://chat.example3.com")));
}

TEST_F(PrefURLListMatcherTest, HostPrecedence) {
  PrefURLListMatcher matcher(&pref_service_, kTestPref);
  SetPref({"copilot.microsoft.com", "microsoft.com"});
  EXPECT_EQ("copilot.microsoft.com",
            *matcher.GetMatchedURL(GURL("https://copilot.microsoft.com/")));
}

TEST_F(PrefURLListMatcherTest, ReturnLastMatchIfHostAndPathLengthsAreEqual) {
  PrefURLListMatcher matcher(&pref_service_, kTestPref);
  // Both patterns result in identical FilterComponents (same host, same path).
  SetPref({"example.com", "http://example.com"});
  EXPECT_EQ("http://example.com",
            *matcher.GetMatchedURL(GURL("https://example.com/")));
  SetPref({"http://example.com", "example.com"});
  EXPECT_EQ("example.com",
            *matcher.GetMatchedURL(GURL("https://example.com/")));
}

TEST_F(PrefURLListMatcherTest, PathPrecedence) {
  PrefURLListMatcher matcher(&pref_service_, kTestPref);
  SetPref({"www.example.com", "www.example.com/p1", "www.example.com/p1/p2"});
  EXPECT_EQ("www.example.com",
            *matcher.GetMatchedURL(GURL("https://www.example.com/p2")));
  EXPECT_EQ("www.example.com/p1",
            *matcher.GetMatchedURL(GURL("https://www.example.com/p1")));
  EXPECT_EQ("www.example.com/p1",
            *matcher.GetMatchedURL(GURL("https://www.example.com/p1/p3")));
  EXPECT_EQ("www.example.com/p1/p2",
            *matcher.GetMatchedURL(GURL("https://www.example.com/p1/p2/p3")));
}

TEST_F(PrefURLListMatcherTest, IgnoredPart) {
  PrefURLListMatcher matcher(&pref_service_, kTestPref);
  SetPref({"http://www.example.com:8088/path?query=text#abc",
           "https://www.example2.com/"});
  EXPECT_EQ("http://www.example.com:8088/path?query=text#abc",
            *matcher.GetMatchedURL(GURL("https://www.example.com/path")));
  EXPECT_FALSE(matcher.GetMatchedURL(GURL("https://www.example.com/p2")));

  EXPECT_EQ("https://www.example2.com/",
            *matcher.GetMatchedURL(GURL("http://www.example2.com")));
}

TEST_F(PrefURLListMatcherTest, Update) {
  PrefURLListMatcher matcher(&pref_service_, kTestPref);
  SetPref({"www.example.com/p1"});
  EXPECT_FALSE(matcher.GetMatchedURL(GURL("https://www.example2.com/p2")));
  SetPref({"www.example.com/p2", "www.example.com/p1"});
  EXPECT_EQ("www.example.com/p2",
            *matcher.GetMatchedURL(GURL("https://www.example.com/p2")));
}

TEST_F(PrefURLListMatcherTest, Localhost) {
  PrefURLListMatcher matcher(&pref_service_, kTestPref);
  SetPref({"localhost", "localhost/path"});
  EXPECT_EQ("localhost/path",
            *matcher.GetMatchedURL(GURL("https://localhost/path2")));
}

TEST_F(PrefURLListMatcherTest, IP) {
  PrefURLListMatcher matcher(&pref_service_, kTestPref);
  SetPref({"192.168.1.1", "192.168.1./path"});

  EXPECT_EQ("192.168.1.1",
            *matcher.GetMatchedURL(GURL("https://192.168.1.1/path2")));
  EXPECT_FALSE(matcher.GetMatchedURL(GURL("https://192.168.1.2/path")));
}

TEST_F(PrefURLListMatcherTest, File) {
  PrefURLListMatcher matcher(&pref_service_, kTestPref);
#if BUILDFLAG(IS_WIN)
  std::string path = "file://c:\\\\path";
#else
  std::string path = "file:///home/path";
#endif

  SetPref({path});
  EXPECT_EQ(path, *matcher.GetMatchedURL(GURL(path)));
}

TEST_F(PrefURLListMatcherTest, Chrome) {
  PrefURLListMatcher matcher(&pref_service_, kTestPref);
  SetPref({"chrome://policy"});
  EXPECT_EQ("chrome://policy",
            *matcher.GetMatchedURL(GURL("chrome://policy/log")));
}

TEST_F(PrefURLListMatcherTest, LongestPathMatchAfterUpdate) {
  PrefURLListMatcher matcher(&pref_service_, kTestPref);
  SetPref({"example.com", "example.com/p1"});
  EXPECT_EQ("example.com/p1",
            *matcher.GetMatchedURL(GURL("https://example.com/p1")));
  SetPref({"example.com/p1", "example.com"});
  EXPECT_EQ("example.com/p1",
            *matcher.GetMatchedURL(GURL("https://example.com/p1")));
}

}  // namespace enterprise_reporting
