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

#include "chrome/browser/ash/login/users/avatar/user_image_manager_impl.h"

#include <memory>
#include <string_view>

#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "chrome/browser/ash/login/users/avatar/mock_user_image_loader_delegate.h"
#include "chrome/browser/ash/login/users/avatar/user_image_loader.h"
#include "chrome/browser/ash/login/users/avatar/user_image_manager_registry.h"
#include "chrome/browser/ash/login/users/avatar/user_image_manager_test_util.h"
#include "chrome/browser/ash/login/users/default_user_image/default_user_images.h"
#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "components/account_id/account_id.h"
#include "components/user_manager/scoped_user_manager.h"
#include "components/user_manager/test_helper.h"
#include "components/user_manager/user.h"
#include "content/public/test/browser_task_environment.h"
#include "google_apis/gaia/gaia_id.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"

namespace ash {
namespace {

constexpr char kFakeRegularUserEmail[] = "test@example.com";

}  // namespace

class UserImageManagerImplTest : public testing::Test {
 public:
  UserImageManagerImplTest() = default;
  UserImageManagerImplTest(const UserImageManagerImplTest&) = delete;
  UserImageManagerImplTest& operator=(const UserImageManagerImplTest&) = delete;
  ~UserImageManagerImplTest() override = default;

  void SetUp() override {
    testing::Test::SetUp();

    ASSERT_TRUE(profile_manager_.SetUp());

    auto mock_user_image_loader_delegate = std::make_unique<
        testing::StrictMock<test::MockUserImageLoaderDelegate>>();
    mock_user_image_loader_delegate_ = mock_user_image_loader_delegate.get();

    user_image_manager_registry_ = std::make_unique<UserImageManagerRegistry>(
        TestingBrowserProcess::GetGlobal()->local_state(),
        fake_chrome_user_manager(), std::move(mock_user_image_loader_delegate));
  }

  void TearDown() override {
    mock_user_image_loader_delegate_ = nullptr;
    testing::Test::TearDown();
  }

  user_manager::User* AddUser(const AccountId& account_id) {
    user_manager::User* user = fake_chrome_user_manager()->AddUser(account_id);
    TestingProfile* profile =
        profile_manager_.CreateTestingProfile(account_id.GetUserEmail());
    fake_chrome_user_manager()->OnUserProfileCreated(account_id,
                                                     profile->GetPrefs());
    return user;
  }

  FakeChromeUserManager* fake_chrome_user_manager() {
    return fake_chrome_user_manager_.Get();
  }

  UserImageManagerRegistry* user_image_manager_registry() {
    return user_image_manager_registry_.get();
  }

  UserImageManagerImpl* user_image_manager_impl(const AccountId& account_id) {
    return user_image_manager_registry()->GetManager(account_id);
  }

  testing::StrictMock<test::MockUserImageLoaderDelegate>*
  mock_user_image_loader_delegate() {
    return mock_user_image_loader_delegate_.get();
  }

  bool is_random_image_set(const AccountId& account_id) {
    return user_image_manager_impl(account_id)->is_random_image_set_;
  }

  bool is_downloading_profile_image(const AccountId& account_id) {
    return user_image_manager_impl(account_id)->downloading_profile_image_;
  }

  bool NeedProfileImage(const AccountId& account_id) {
    return user_image_manager_impl(account_id)->NeedProfileImage();
  }

 private:
  content::BrowserTaskEnvironment task_environment_;
  TestingProfileManager profile_manager_{TestingBrowserProcess::GetGlobal()};
  user_manager::TypedScopedUserManager<FakeChromeUserManager>
      fake_chrome_user_manager_{std::make_unique<FakeChromeUserManager>()};
  raw_ptr<testing::StrictMock<test::MockUserImageLoaderDelegate>>
      mock_user_image_loader_delegate_;
  std::unique_ptr<UserImageManagerRegistry> user_image_manager_registry_;
};

TEST_F(UserImageManagerImplTest, RecordsUserImageLoggedInHistogram) {
  constexpr int kDefaultImageIndex = 85;
  ASSERT_TRUE(default_user_image::IsInCurrentImageSet(kDefaultImageIndex));

  base::HistogramTester histogram_tester;

  const AccountId account_id = AccountId::FromUserEmailGaiaId(
      std::string(kFakeRegularUserEmail), GaiaId("1111"));
  AddUser(account_id);

  EXPECT_CALL(*mock_user_image_loader_delegate(), FromGURLAnimated);

  user_image_manager_impl(account_id)
      ->SaveUserDefaultImageIndex(kDefaultImageIndex);

  fake_chrome_user_manager()->SetIsCurrentUserNew(false);
  fake_chrome_user_manager()->UserLoggedIn(
      account_id, /*user_id_hash=*/
      user_manager::TestHelper::GetFakeUsernameHash(account_id));

  histogram_tester.ExpectUniqueSample(
      UserImageManagerImpl::kUserImageLoggedInHistogramName,
      UserImageManagerImpl::ImageIndexToHistogramIndex(kDefaultImageIndex), 1);
}

}  // namespace ash
