// Copyright 2023 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/policy/core/reporting_user_tracker.h"

#include <algorithm>
#include <utility>

#include "ash/constants/ash_policy_pref_names.h"
#include "base/check_is_test.h"
#include "base/values.h"
#include "components/account_id/account_id.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "google_apis/gaia/gaia_auth_util.h"

namespace policy {
namespace {

std::string FullyCanonicalize(const std::string& email) {
  return gaia::CanonicalizeEmail(gaia::SanitizeEmail(email));
}

}  // namespace

ReportingUserTracker::ReportingUserTracker(
    user_manager::UserManager* user_manager)
    : local_state_(user_manager->GetLocalState()) {
  observation_.Observe(user_manager);
}

ReportingUserTracker::~ReportingUserTracker() = default;

// static
void ReportingUserTracker::RegisterPrefs(PrefRegistrySimple* registry) {
  registry->RegisterListPref(ash::prefs::kReportingUsers);
}

bool ReportingUserTracker::ShouldReportUser(
    const std::string& user_email) const {
  const base::ListValue& reporting_users =
      local_state_->GetList(ash::prefs::kReportingUsers);
  std::string user_email_value(FullyCanonicalize(user_email));
  return reporting_users.contains(user_email_value);
}

void ReportingUserTracker::OnUserAffiliationUpdated(
    const user_manager::User& user) {
  if (!local_state_) {
    // On unittests, |LocalState| may not be initialized.
    // TODO(b/267685577): Consider getting rid of this.
    CHECK_IS_TEST();
    return;
  }

  if (user.GetType() != user_manager::UserType::kRegular) {
    return;
  }

  const AccountId& account_id = user.GetAccountId();
  if (user.IsAffiliated()) {
    AddReportingUser(account_id);
  } else {
    RemoveReportingUser(account_id);
  }
}

void ReportingUserTracker::OnUserRemoved(
    const AccountId& account_id,
    user_manager::UserRemovalReason reason) {
  if (!local_state_) {
    // On unittests, |LocalState| may not be initialized.
    // TODO(b/267685577): Consider getting rid of this.
    CHECK_IS_TEST();
    return;
  }

  RemoveReportingUser(account_id);
}

void ReportingUserTracker::AddReportingUser(const AccountId& account_id) {
  ScopedListPrefUpdate users_update(local_state_, ash::prefs::kReportingUsers);
  std::string email(FullyCanonicalize(account_id.GetUserEmail()));
  if (!users_update.Get().contains(email)) {
    users_update->Append(email);
  }
}

void ReportingUserTracker::RemoveReportingUser(const AccountId& account_id) {
  ScopedListPrefUpdate users_update(local_state_, ash::prefs::kReportingUsers);
  base::ListValue& update_list = users_update.Get();
  auto it = std::ranges::find(
      update_list, base::Value(FullyCanonicalize(account_id.GetUserEmail())));
  if (it == update_list.end()) {
    return;
  }
  update_list.erase(it);
}

}  // namespace policy
