// Copyright 2020 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/ui/webui/ash/settings/pages/people/people_section.h"

#include <array>
#include <vector>

#include "ash/constants/ash_features.h"
#include "ash/constants/ash_pref_names.h"
#include "ash/constants/chrome_webui_url_constants.h"
#include "ash/constants/url_constants.h"
#include "ash/edusumer/graduation_utils.h"
#include "ash/strings/grit/ash_strings.h"
#include "base/check.h"
#include "base/check_deref.h"
#include "base/check_op.h"
#include "base/containers/span.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/i18n/number_formatting.h"
#include "base/metrics/histogram_functions.h"
#include "base/no_destructor.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/ash/account_manager/account_apps_availability.h"
#include "chrome/browser/ash/account_manager/account_apps_availability_factory.h"
#include "chrome/browser/ash/account_manager/account_manager_util.h"
#include "chrome/browser/ash/login/quick_unlock/quick_unlock_utils.h"
#include "chrome/browser/ash/profiles/profile_helper.h"
#include "chrome/browser/policy/profile_policy_connector.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/ui_features.h"
#include "chrome/browser/ui/webui/ash/settings/os_settings_features_util.h"
#include "chrome/browser/ui/webui/ash/settings/pages/people/account_manager_ui_handler.h"
#include "chrome/browser/ui/webui/ash/settings/pages/people/fingerprint_handler.h"
#include "chrome/browser/ui/webui/ash/settings/pages/people/parental_controls_handler.h"
#include "chrome/browser/ui/webui/ash/settings/pages/people/quick_unlock_handler.h"
#include "chrome/browser/ui/webui/ash/settings/search/search_tag_registry.h"
#include "chrome/browser/ui/webui/settings/people_handler.h"
#include "chrome/browser/ui/webui/settings/profile_info_handler.h"
#include "chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.h"
#include "chrome/grit/branded_strings.h"
#include "chrome/grit/browser_resources.h"
#include "chrome/grit/generated_resources.h"
#include "chromeos/ash/components/account_manager/account_manager_factory.h"
#include "chromeos/ash/components/browser_context_helper/browser_context_helper.h"
#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
#include "components/account_manager_core/pref_names.h"
#include "components/omnibox/common/omnibox_features.h"
#include "components/prefs/pref_service.h"
#include "components/strings/grit/components_strings.h"
#include "components/user_manager/user.h"
#include "components/user_manager/user_manager.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
#include "google_apis/gaia/gaia_id.h"
#include "services/network/public/mojom/content_security_policy.mojom.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/webui/web_ui_util.h"
#include "ui/chromeos/devicetype_utils.h"
#include "ui/chromeos/resources/grit/ui_chromeos_resources.h"
#include "ui/webui/webui_util.h"

namespace ash::settings {

namespace mojom {
using ::chromeos::settings::mojom::kPeopleSectionPath;
using ::chromeos::settings::mojom::Section;
using ::chromeos::settings::mojom::Setting;
using ::chromeos::settings::mojom::Subpage;
}  // namespace mojom

namespace {

base::span<const SearchConcept> GetPeopleSearchConcepts() {
  static constexpr auto tags = std::to_array<SearchConcept>({
      {IDS_OS_SETTINGS_TAG_PEOPLE_V2,
       mojom::kPeopleSectionPath,
       mojom::SearchResultIcon::kAvatar,
       mojom::SearchResultDefaultRank::kMedium,
       mojom::SearchResultType::kSection,
       {.section = mojom::Section::kPeople},
       {IDS_OS_SETTINGS_TAG_PEOPLE_ACCOUNTS, IDS_OS_SETTINGS_TAG_PEOPLE,
        SearchConcept::kAltTagEnd}},
      {IDS_OS_SETTINGS_TAG_PEOPLE_ACCOUNTS_ADD_V2,
       mojom::kPeopleSectionPath,
       mojom::SearchResultIcon::kAvatar,
       mojom::SearchResultDefaultRank::kMedium,
       mojom::SearchResultType::kSetting,
       {.setting = mojom::Setting::kAddAccount}},
  });

  return tags;
}

base::span<const SearchConcept> GetRemoveAccountSearchConcepts() {
  static constexpr auto tags = std::to_array<SearchConcept>({
      {IDS_OS_SETTINGS_TAG_PEOPLE_ACCOUNTS_REMOVE,
       mojom::kPeopleSectionPath,
       mojom::SearchResultIcon::kAvatar,
       mojom::SearchResultDefaultRank::kMedium,
       mojom::SearchResultType::kSetting,
       {.setting = mojom::Setting::kRemoveAccount}},
  });
  return tags;
}

base::span<const SearchConcept> GetParentalSearchConcepts() {
  static constexpr auto tags = std::to_array<SearchConcept>({
      {IDS_OS_SETTINGS_TAG_PARENTAL_CONTROLS,
       mojom::kPeopleSectionPath,
       mojom::SearchResultIcon::kAvatar,
       mojom::SearchResultDefaultRank::kMedium,
       mojom::SearchResultType::kSetting,
       {.setting = mojom::Setting::kSetUpParentalControls},
       {IDS_OS_SETTINGS_TAG_PARENTAL_CONTROLS_ALT1,
        IDS_OS_SETTINGS_TAG_PARENTAL_CONTROLS_ALT2, SearchConcept::kAltTagEnd}},
  });
  return tags;
}

base::span<const SearchConcept> GetGraduationSearchConcepts() {
  static constexpr auto tags = std::to_array<SearchConcept>({
      {IDS_OS_SETTINGS_TAG_GRADUATION,
       mojom::kPeopleSectionPath,
       mojom::SearchResultIcon::kGraduation,
       mojom::SearchResultDefaultRank::kMedium,
       mojom::SearchResultType::kSetting,
       {.setting = mojom::Setting::kGraduation}},
  });
  return tags;
}

void AddAccountManagerPageStrings(content::WebUIDataSource* html_source,
                                  Profile* profile) {
  static constexpr webui::LocalizedString kLocalizedStrings[] = {
      {"accountManagerChildFirstMessage",
       IDS_SETTINGS_ACCOUNT_MANAGER_CHILD_FIRST_MESSAGE},
      {"accountManagerChildSecondMessage",
       IDS_SETTINGS_ACCOUNT_MANAGER_CHILD_SECOND_MESSAGE},
      {"accountManagerEducationAccountLabel",
       IDS_SETTINGS_ACCOUNT_MANAGER_EDUCATION_ACCOUNT},
      {"removeAccountLabel", IDS_SETTINGS_ACCOUNT_MANAGER_REMOVE_ACCOUNT_LABEL},
      {"addSchoolAccountLabel",
       IDS_SETTINGS_ACCOUNT_MANAGER_ADD_SCHOOL_ACCOUNT_LABEL},
      {"accountManagerSecondaryAccountsDisabledChildText",
       IDS_SETTINGS_ACCOUNT_MANAGER_SECONDARY_ACCOUNTS_DISABLED_CHILD_TEXT},
      {"accountManagerSignedOutAccountName",
       IDS_SETTINGS_ACCOUNT_MANAGER_SIGNED_OUT_ACCOUNT_PLACEHOLDER},
      {"accountManagerUnmigratedAccountName",
       IDS_SETTINGS_ACCOUNT_MANAGER_UNMIGRATED_ACCOUNT_PLACEHOLDER},
      {"accountManagerMigrationLabel",
       IDS_SETTINGS_ACCOUNT_MANAGER_MIGRATION_LABEL},
      {"accountManagerReauthenticationLabel",
       IDS_SETTINGS_ACCOUNT_MANAGER_REAUTHENTICATION_LABEL},
      {"accountManagerMigrationTooltip",
       IDS_SETTINGS_ACCOUNT_MANAGER_MIGRATION_TOOLTIP},
      {"accountManagerReauthenticationTooltip",
       IDS_SETTINGS_ACCOUNT_MANAGER_REAUTHENTICATION_TOOLTIP},
      {"accountManagerMoreActionsTooltip",
       IDS_SETTINGS_ACCOUNT_MANAGER_MORE_ACTIONS_TOOLTIP},
      {"addAccountLabel", IDS_SETTINGS_ACCOUNT_MANAGER_ADD_ACCOUNT_LABEL_V2},
      {"accountListHeader", IDS_SETTINGS_ACCOUNT_MANAGER_LIST_HEADER_V2},
      {"accountListHeaderChild",
       IDS_SETTINGS_ACCOUNT_MANAGER_LIST_HEADER_CHILD},
      {"accountManagerChildDescription",
       IDS_SETTINGS_ACCOUNT_MANAGER_CHILD_DESCRIPTION_V2},
      {"accountManagerSecondaryAccountsDisabledText",
       IDS_SETTINGS_ACCOUNT_MANAGER_SECONDARY_ACCOUNTS_DISABLED_TEXT_V2},
      {"accountNotAllowedInArcLabel",
       IDS_SETTINGS_ACCOUNT_MANAGER_NOT_ALLOWED_IN_ARC_LABEL},
      {"accountUseInArcButtonLabel",
       IDS_SETTINGS_ACCOUNT_MANAGER_USE_IN_ARC_BUTTON_LABEL},
      {"accountStopUsingInArcButtonLabel",
       IDS_SETTINGS_ACCOUNT_MANAGER_STOP_USING_IN_ARC_BUTTON_LABEL},
  };
  html_source->AddLocalizedStrings(kLocalizedStrings);
  html_source->AddLocalizedString(
      "accountListDescription", IDS_SETTINGS_ACCOUNT_MANAGER_LIST_DESCRIPTION);

  user_manager::User* user = ProfileHelper::Get()->GetUserByProfile(profile);
  DCHECK(user);
  html_source->AddString(
      "accountListChildDescription",
      l10n_util::GetStringFUTF16(
          IDS_SETTINGS_ACCOUNT_MANAGER_LIST_CHILD_DESCRIPTION,
          base::UTF8ToUTF16(user->GetDisplayEmail())));

  html_source->AddString("accountManagerLearnMoreUrl",
                         ash::external_urls::kAccountManagerLearnMoreURL);
  html_source->AddLocalizedString(
      "accountManagerManagementDescription",
      profile->IsChild() ? IDS_SETTINGS_ACCOUNT_MANAGER_MANAGEMENT_STATUS_CHILD
                         : IDS_SETTINGS_ACCOUNT_MANAGER_MANAGEMENT_STATUS);
  html_source->AddString("accountManagerChromeUIManagementURL",
                         ash::chrome_urls::kChromeUIManagementURL16);
  html_source->AddString(
      "accountManagerDescription",
      l10n_util::GetStringFUTF16(IDS_SETTINGS_ACCOUNT_MANAGER_DESCRIPTION_V2,
                                 ui::GetChromeOSDeviceName()));
}

void AddLockScreenPageStrings(content::WebUIDataSource* html_source,
                              Profile* profile) {
  static constexpr webui::LocalizedString kLocalizedStrings[] = {
      {"lockScreenNotificationTitle",
       IDS_ASH_SETTINGS_LOCK_SCREEN_NOTIFICATION_TITLE},
      {"lockScreenNotificationHideSensitive",
       IDS_ASH_SETTINGS_LOCK_SCREEN_NOTIFICATION_HIDE_SENSITIVE},
      {"enableScreenlock", IDS_SETTINGS_PEOPLE_ENABLE_SCREENLOCK},
      {"lockScreenNotificationShow",
       IDS_ASH_SETTINGS_LOCK_SCREEN_NOTIFICATION_SHOW},
      {"lockScreenPinOrPassword",
       IDS_SETTINGS_PEOPLE_LOCK_SCREEN_PIN_OR_PASSWORD},
      {"lockScreenPinOnly", IDS_SETTINGS_PEOPLE_LOCK_SCREEN_PIN_ONLY},
      {"lockScreenPasswordOrFingerprint",
       IDS_SETTINGS_PEOPLE_LOCK_SCREEN_PASSWORD_OR_FINGERPRINT},
      {"lockScreenPinOrFingerprint",
       IDS_SETTINGS_PEOPLE_LOCK_SCREEN_PIN_OR_FINGERPRINT},
      {"lockScreenPasswordOrPinOrFingerprint",
       IDS_SETTINGS_PEOPLE_LOCK_SCREEN_PASSWORD_OR_PIN_OR_FINGERPRINT},
      {"lockScreenNoAuthFactor", IDS_SETTINGS_PEOPLE_LOCK_SCREEN_NO_AUTH},
      {"lockScreenPinMoreButtonAriaLabel",
       IDS_SETTINGS_PEOPLE_LOCK_SCREEN_PIN_MORE_BUTTON_ARIA_LABEL},
      {"lockScreenPinAutoSubmit",
       IDS_SETTINGS_PEOPLE_LOCK_SCREEN_PIN_AUTOSUBMIT},
      {"lockScreenSetupFingerprintButton",
       IDS_SETTINGS_PEOPLE_LOCK_SCREEN_FINGERPRINT_SETUP_BUTTON},
      {"lockScreenNotificationHide",
       IDS_ASH_SETTINGS_LOCK_SCREEN_NOTIFICATION_HIDE},
      {"lockScreenEditFingerprints",
       IDS_SETTINGS_PEOPLE_LOCK_SCREEN_EDIT_FINGERPRINTS},
      {"lockScreenPasswordOnly", IDS_SETTINGS_PEOPLE_LOCK_SCREEN_PASSWORD_ONLY},
      {"lockScreenChangePasswordButton",
       IDS_SETTINGS_PEOPLE_LOCK_SCREEN_CHANGE_PASSWORD_BUTTON},
      {"lockScreenChangePinButton",
       IDS_SETTINGS_PEOPLE_LOCK_SCREEN_CHANGE_PIN_BUTTON},
      {"lockScreenEditFingerprintsDescription",
       IDS_SETTINGS_PEOPLE_LOCK_SCREEN_EDIT_FINGERPRINTS_DESCRIPTION},
      {"lockScreenNone", IDS_SETTINGS_PEOPLE_LOCK_SCREEN_NONE},
      {"lockScreenFingerprintNewName",
       IDS_SETTINGS_PEOPLE_LOCK_SCREEN_NEW_FINGERPRINT_DEFAULT_NAME},
      {"lockScreenDeleteFingerprintLabel",
       IDS_SETTINGS_PEOPLE_LOCK_SCREEN_DELETE_FINGERPRINT_ARIA_LABEL},
      {"lockScreenOptionsLock", IDS_SETTINGS_PEOPLE_LOCK_SCREEN_OPTIONS_LOCK},
      {"lockScreenOptionsLoginLock",
       IDS_SETTINGS_PEOPLE_LOCK_SCREEN_OPTIONS_LOGIN_LOCK},
      {"lockScreenRemoveButton",
       IDS_SETTINGS_PEOPLE_LOCK_SCREEN_REMOVE_PIN_BUTTON},
      {"lockScreenPasswordLabel",
       IDS_SETTINGS_PEOPLE_LOCK_SCREEN_PASSWORD_LABEL},
      {"lockScreenPinLabel", IDS_SETTINGS_PEOPLE_LOCK_SCREEN_PIN_LABEL},
      {"lockScreenSetupPasswordButton",
       IDS_SETTINGS_PEOPLE_LOCK_SCREEN_SETUP_PASSWORD_BUTTON},
      {"lockScreenSetupPinButton",
       IDS_SETTINGS_PEOPLE_LOCK_SCREEN_SETUP_PIN_BUTTON},
      {"lockScreenSignInOptions",
       IDS_SETTINGS_PEOPLE_LOCK_SCREEN_SIGN_IN_OPTIONS},
      {"lockScreenTitleLock", IDS_SETTINGS_PEOPLE_LOCK_SCREEN_TITLE_LOCK},
      {"lockScreenTitleLoginLock",
       IDS_SETTINGS_PEOPLE_LOCK_SCREEN_TITLE_LOGIN_LOCK_V2},
      {"passwordPromptEnterPasswordLock",
       IDS_SETTINGS_PEOPLE_PASSWORD_PROMPT_ENTER_PASSWORD_LOCK},
      {"pinAutoSubmitPrompt",
       IDS_SETTINGS_PEOPLE_LOCK_SCREEN_PIN_AUTOSUBMIT_PROMPT},
      {"pinAutoSubmitLongPinError",
       IDS_SETTINGS_PEOPLE_LOCK_SCREEN_PIN_AUTOSUBMIT_ERROR_PIN_TOO_LONG},
      {"pinAutoSubmitPinIncorrect",
       IDS_SETTINGS_PEOPLE_LOCK_SCREEN_PIN_AUTOSUBMIT_ERROR_PIN_INCORRECT},
      {"passwordPromptEnterPasswordLoginLock",
       IDS_SETTINGS_PEOPLE_PASSWORD_PROMPT_ENTER_PASSWORD_LOGIN_LOCK},
      {"recoveryToggleLabel", IDS_SETTINGS_PEOPLE_RECOVERY_TOGGLE_LABEL},
      {"recoveryToggleSubLabel", IDS_SETTINGS_PEOPLE_RECOVERY_TOGGLE_SUB_LABEL},
      {"recoveryDisableDialogTitle",
       IDS_SETTINGS_PEOPLE_RECOVERY_DISABLE_DIALOG_TITLE},
      {"recoveryDisableDialogMessage",
       IDS_SETTINGS_PEOPLE_RECOVERY_DISABLE_DIALOG_MESSAGE},
      {"recoveryNotSupportedMessage",
       IDS_SETTINGS_PEOPLE_RECOVERY_NOT_SUPPORTED_MESSAGE},
      {"setLocalPasswordDialogTitle",
       IDS_OS_SETTINGS_PEOPLE_SET_LOCAL_PASSWORD_DIALOG_TITLE},
      {"setLocalPasswordDialogInternalError",
       IDS_OS_SETTINGS_PEOPLE_SET_LOCAL_PASSWORD_DIALOG_INTERNAL_ERROR},
      {"showPassword", IDS_AUTH_SETUP_SHOW_PASSWORD},
      {"hidePassword", IDS_AUTH_SETUP_HIDE_PASSWORD},
      {"showPin", IDS_AUTH_SETUP_SHOW_PIN},
      {"hidePin", IDS_AUTH_SETUP_HIDE_PIN},
      {"setLocalPasswordPlaceholder",
       IDS_AUTH_SETUP_SET_LOCAL_PASSWORD_PLACEHOLDER},
      {"setLocalPasswordConfirmPlaceholder",
       IDS_AUTH_SETUP_SET_LOCAL_PASSWORD_CONFIRM_PLACEHOLDER},
      {"setLocalPasswordMinCharsHint",
       IDS_AUTH_SETUP_SET_LOCAL_PASSWORD_MIN_CHARS_HINT},
      {"setLocalPasswordErrorTooShort",
       IDS_AUTH_SETUP_SET_LOCAL_PASSWORD_ERROR_TOO_SHORT},
      {"setLocalPasswordErrorContainsTrivialSequence",
       IDS_AUTH_SETUP_SET_LOCAL_PASSWORD_ERROR_CONTAINS_TRIVIAL_SEQUENCE},
      {"setLocalPasswordReqLetterOrSymbol",
       IDS_AUTH_SETUP_SET_LOCAL_PASSWORD_REQ_LETTER_OR_SYMBOL},
      {"setLocalPasswordReqTwoClasses",
       IDS_AUTH_SETUP_SET_LOCAL_PASSWORD_REQ_TWO_CLASSES},
      {"setLocalPasswordReqFourClasses",
       IDS_AUTH_SETUP_SET_LOCAL_PASSWORD_REQ_FOUR_CLASSES},
      {"setLocalPasswordComplexityErrorNone",
       IDS_AUTH_SETUP_SET_LOCAL_PASSWORD_COMPLEXITY_ERROR_NONE},
      {"setLocalPasswordComplexityErrorLow",
       IDS_AUTH_SETUP_SET_LOCAL_PASSWORD_COMPLEXITY_ERROR_LOW},
      {"setLocalPasswordComplexityErrorMedium",
       IDS_AUTH_SETUP_SET_LOCAL_PASSWORD_COMPLEXITY_ERROR_MEDIUM},
      {"setLocalPasswordComplexityErrorHigh",
       IDS_AUTH_SETUP_SET_LOCAL_PASSWORD_COMPLEXITY_ERROR_HIGH},
      {"setLocalPasswordNoMatchError",
       IDS_AUTH_SETUP_SET_LOCAL_PASSWORD_NO_MATCH_ERROR},
  };
  html_source->AddLocalizedStrings(kLocalizedStrings);

  html_source->AddBoolean("quickUnlockEnabled", quick_unlock::IsPinEnabled());
  html_source->AddBoolean(
      "quickUnlockDisabledByPolicy",
      quick_unlock::IsPinDisabledByPolicy(profile->GetPrefs(),
                                          quick_unlock::Purpose::kAny));
  html_source->AddString(
      "lockScreenSwitchLocalPasswordDescription",
      l10n_util::GetStringFUTF16(
          IDS_SETTINGS_PEOPLE_LOCK_SCREEN_SWITCH_LOCAL_PASSWORD_DESCRIPTION,
          ui::GetChromeOSDeviceName()));
  html_source->AddString(
      "lockScreenSwitchSetLocalPasswordDescription",
      l10n_util::GetStringFUTF16(
          IDS_SETTINGS_PEOPLE_LOCK_SCREEN_PASSWORD_DESCRIPTION,
          ui::GetChromeOSDeviceName()));
  html_source->AddString("lockScreenFingerprintNotice",
                         l10n_util::GetStringFUTF16(
                             IDS_SETTINGS_PEOPLE_LOCK_SCREEN_FINGERPRINT_NOTICE,
                             ui::GetChromeOSDeviceName()));
  html_source->AddString("fingerprintLearnMoreLink",
                         ash::external_urls::kFingerprintLearnMoreURL);
  html_source->AddString("recoveryLearnMoreUrl",
                         ash::external_urls::kRecoveryLearnMoreURL);
  html_source->AddBoolean("managedLocalPinAndPasswordEnabled",
                          ash::features::IsManagedLocalPinAndPasswordEnabled());
}

void AddFingerprintListStrings(content::WebUIDataSource* html_source) {
  static constexpr webui::LocalizedString kLocalizedStrings[] = {
      {"lockScreenAddFingerprint",
       IDS_SETTINGS_PEOPLE_LOCK_SCREEN_ADD_FINGERPRINT_BUTTON},
      {"lockScreenRegisteredFingerprints",
       IDS_SETTINGS_PEOPLE_LOCK_SCREEN_REGISTERED_FINGERPRINTS_LABEL},
      {"lockScreenFingerprintWarning",
       IDS_SETTINGS_PEOPLE_LOCK_SCREEN_FINGERPRINT_LESS_SECURE},
  };
  html_source->AddLocalizedStrings(kLocalizedStrings);
}

void AddFingerprintResources(content::WebUIDataSource* html_source,
                             bool are_fingerprint_settings_allowed) {
  html_source->AddBoolean("fingerprintUnlockEnabled",
                          are_fingerprint_settings_allowed);

  html_source->AddResourcePath("fingerprint_scanner_animation.json",
                               IDR_FINGERPRINT_DEFAULT_ANIMATION);

  if (are_fingerprint_settings_allowed) {
    quick_unlock::AddFingerprintResources(html_source);
  }

  auto fp_setup_strings = quick_unlock::GetFingerprintDescriptionStrings(
      quick_unlock::GetFingerprintLocation());
  html_source->AddString(
      "configureFingerprintInstructionLocateScannerStep",
      l10n_util::GetStringFUTF16(fp_setup_strings.description_id,
                                 ui::GetChromeOSDeviceName()));
}

void AddSetupFingerprintDialogStrings(content::WebUIDataSource* html_source) {
  static constexpr webui::LocalizedString kLocalizedStrings[] = {
      {"configureFingerprintTitle", IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_TITLE},
      {"configureFingerprintAddAnotherButton",
       IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_ADD_ANOTHER_BUTTON},
      {"configureFingerprintInstructionReadyStep",
       IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_INSTRUCTION_READY},
      {"configureFingerprintLiftFinger",
       IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_LIFT_FINGER},
      {"configureFingerprintTryAgain",
       IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_TRY_AGAIN},
      {"configureFingerprintImmobile",
       IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_FINGER_IMMOBILE},
  };
  html_source->AddLocalizedStrings(kLocalizedStrings);
}

void AddSetupPinDialogStrings(content::WebUIDataSource* html_source) {
  static constexpr webui::LocalizedString kLocalizedStrings[] = {
      {"configurePinChoosePinTitle",
       IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_CHOOSE_PIN_TITLE},
      {"configurePinConfirmPinTitle",
       IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_CONFIRM_PIN_TITLE},
      {"configurePinMismatched", IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_MISMATCHED},
      {"configurePinTooShort", IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_TOO_SHORT},
      {"configurePinTooLong", IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_TOO_LONG},
      {"configurePinWeakPin", IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_WEAK_PIN},
      {"configurePinNondigit", IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_NONDIGIT},
      {"internalError", IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_INTERNAL_ERROR},
      {"configurePinComplexityErrorNone",
       IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_COMPLEXITY_ERROR_NONE},
      {"configurePinComplexityErrorLow",
       IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_COMPLEXITY_ERROR_LOW},
      {"configurePinComplexityErrorMedium",
       IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_COMPLEXITY_ERROR_MEDIUM},
      {"configurePinComplexityErrorHigh",
       IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_COMPLEXITY_ERROR_HIGH},
      {"configurePinComplexityRepeating",
       IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_REPEATING_DIGITS},
      {"configurePinComplexityOrdered",
       IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_ORDERED_SEQUENCE},
      {"configurePinComplexityTooShort",
       IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_COMPLEXITY_TOO_SHORT},
      {"pinKeyboardPlaceholderPin", IDS_PIN_KEYBOARD_HINT_TEXT_PIN},
      {"pinKeyboardPlaceholderPinPassword",
       IDS_PIN_KEYBOARD_HINT_TEXT_PIN_PASSWORD},
      {"pinKeyboardDeleteAccessibleName",
       IDS_PIN_KEYBOARD_DELETE_ACCESSIBLE_NAME},
  };
  html_source->AddLocalizedStrings(kLocalizedStrings);

  // Format numbers to be used on the pin keyboard.
  for (int j = 0; j <= 9; j++) {
    html_source->AddString("pinKeyboard" + base::NumberToString(j),
                           base::FormatNumber(int64_t{j}));
  }
}

void AddUsersStrings(content::WebUIDataSource* html_source) {
  webui::LocalizedString kLocalizedStrings[] = {
      {"usersModifiedByOwnerLabel", IDS_SETTINGS_USERS_MODIFIED_BY_OWNER_LABEL},
      {"guestBrowsingLabel", IDS_OS_SETTINGS_USERS_GUEST_BROWSING_LABEL},
      {"settingsManagedLabel", IDS_SETTINGS_USERS_MANAGED_LABEL},
      {"showOnSigninLabel", IDS_SETTINGS_USERS_SHOW_ON_SIGNIN_LABEL},
      {"restrictSigninLabel", IDS_OS_SETTINGS_USERS_RESTRICT_SIGNIN_LABEL},
      {"restrictSigninDescription",
       IDS_OS_SETTINGS_USERS_RESTRICT_SIGNIN_DESCRIPTION},
      {"deviceOwnerLabel", IDS_SETTINGS_USERS_DEVICE_OWNER_LABEL},
      {"removeUserTooltip", IDS_SETTINGS_USERS_REMOVE_USER_TOOLTIP},
      {"userRemovedMessage", IDS_SETTINGS_USERS_USER_REMOVED_MESSAGE},
      {"userAddedMessage", IDS_SETTINGS_USERS_USER_ADDED_MESSAGE},
      {"addUsers", IDS_SETTINGS_USERS_ADD_USERS},
      {"addUsersEmail", IDS_SETTINGS_USERS_ADD_USERS_EMAIL},
      {"userExistsError", IDS_SETTINGS_USER_EXISTS_ERROR},
  };
  html_source->AddLocalizedStrings(kLocalizedStrings);
}

void AddParentalControlStrings(content::WebUIDataSource* html_source,
                               bool are_parental_control_settings_allowed) {
  static constexpr webui::LocalizedString kLocalizedStrings[] = {
      {"parentalControlsPageTitle", IDS_SETTINGS_PARENTAL_CONTROLS_PAGE_TITLE},
      {"parentalControlsPageSetUpLabel",
       IDS_SETTINGS_PARENTAL_CONTROLS_PAGE_SET_UP_LABEL},
      {"parentalControlsPageViewSettingsLabel",
       IDS_SETTINGS_PARENTAL_CONTROLS_PAGE_VIEW_SETTINGS_LABEL},
      {"parentalControlsPageConnectToInternetLabel",
       IDS_SETTINGS_PARENTAL_CONTROLS_PAGE_CONNECT_TO_INTERNET_LABEL},
      {"parentalControlsSetUpButtonLabel",
       IDS_SETTINGS_PARENTAL_CONTROLS_SET_UP_BUTTON_LABEL},
      {"parentalControlsSetUpButtonRole",
       IDS_SETTINGS_PARENTAL_CONTROLS_SET_UP_BUTTON_ROLE},
  };
  html_source->AddLocalizedStrings(kLocalizedStrings);

  html_source->AddBoolean("showParentalControls",
                          are_parental_control_settings_allowed);
}

void AddGraduationStrings(content::WebUIDataSource* html_source,
                          Profile* profile) {
  static constexpr webui::LocalizedString kLocalizedStrings[] = {
      {"graduationSectionTitle", IDS_SETTINGS_GRADUATION_SECTION_TITLE},
      {"graduationRowTitle", IDS_SETTINGS_GRADUATION_ROW_TITLE},
      {"graduationRowSubtitle", IDS_SETTINGS_GRADUATION_ROW_SUBTITLE}};

  html_source->AddLocalizedStrings(kLocalizedStrings);

  html_source->AddBoolean("isGraduationAppEnabled",
                          ShouldShowGraduationAppSetting(profile));
  html_source->AddBoolean("isGraduationFlagEnabled",
                          features::IsGraduationEnabled());
}

bool IsSameAccount(const ::account_manager::AccountKey& account_key,
                   const AccountId& account_id) {
  // Currently, we only support `kGaia` account type. Should a new type be added
  // in the future, consider removing the `CHECK_EQ()` below and handling the
  // new type accordingly.
  CHECK_EQ(account_key.account_type(), account_manager::AccountType::kGaia);

  return (account_id.GetAccountType() == AccountType::GOOGLE) &&
         (account_id.GetGaiaId() == GaiaId(account_key.id()));
}

}  // namespace

PeopleSection::PeopleSection(Profile* profile,
                             SearchTagRegistry* search_tag_registry,
                             signin::IdentityManager* identity_manager,
                             PrefService* pref_service)
    : OsSettingsSection(profile, search_tag_registry),
      identity_manager_(identity_manager),
      pref_service_(pref_service),
      auth_performer_(UserDataAuthClient::Get()),
      fp_engine_(&auth_performer_) {
  // No search tags are registered if in guest mode.
  const auto& user = CHECK_DEREF(
      BrowserContextHelper::Get()->GetUserByBrowserContext(profile));
  if (IsGuestModeActive(user)) {
    return;
  }

  SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate();
  updater.AddSearchTags(GetPeopleSearchConcepts());

  // TODO(jamescook): Sort out how account management is split between Chrome
  // OS and browser settings.
  if (IsAccountManagerAvailable(profile)) {
    // Some Account Manager search tags are added/removed dynamically.
    account_manager_ = AccountManagerFactory::Get()->GetAccountManager(
        profile->GetPath().value());
    DCHECK(account_manager_);
    account_manager_facade_ =
        AccountManagerFactory::Get()->GetAccountManagerFacade(
            profile->GetPath().value());
    DCHECK(account_manager_facade_);
    account_manager_observation_.Observe(account_manager_.get());
    account_apps_availability_ =
        AccountAppsAvailabilityFactory::GetForProfile(profile);
    FetchAccounts();
  }

  // Parental control search tags are added if necessary and do not update
  // dynamically during a user session.
  if (ShouldShowParentalControlSettings(profile)) {
    updater.AddSearchTags(GetParentalSearchConcepts());
  }
  if (features::IsGraduationEnabled() &&
      ShouldShowGraduationAppSetting(profile)) {
    updater.AddSearchTags(GetGraduationSearchConcepts());
  }
}

PeopleSection::~PeopleSection() = default;

void PeopleSection::AddLoadTimeData(content::WebUIDataSource* html_source) {
  static constexpr webui::LocalizedString kLocalizedStrings[] = {
      {"osPeoplePageTitle", IDS_OS_SETTINGS_PEOPLE_V2},
      {"accountsMenuItemDescription",
       IDS_OS_SETTINGS_ACCOUNTS_MENU_ITEM_DESCRIPTION},
      {"accountManagerSubMenuLabel",
       IDS_SETTINGS_ACCOUNT_MANAGER_SUBMENU_LABEL},
      {"accountManagerPageTitle", IDS_SETTINGS_ACCOUNT_MANAGER_PAGE_TITLE},
      {"lockScreenFingerprintTitle",
       IDS_SETTINGS_PEOPLE_LOCK_SCREEN_FINGERPRINT_SUBPAGE_TITLE},
      {"manageOtherPeople", IDS_SETTINGS_PEOPLE_MANAGE_OTHER_PEOPLE},
  };
  html_source->AddLocalizedStrings(kLocalizedStrings);

  user_manager::User* user = ProfileHelper::Get()->GetUserByProfile(profile());
  DCHECK(user);

  html_source->AddString(
      "osProfileName", l10n_util::GetStringFUTF16(IDS_OS_SETTINGS_PROFILE_NAME,
                                                  user->GetGivenName()));
  html_source->AddString(
      "accountManagerPageTitle",
      l10n_util::GetStringFUTF16(IDS_SETTINGS_ACCOUNT_MANAGER_PAGE_TITLE_V2,
                                 user->GetGivenName()));

  // Toggles the ChromeOS Account Manager submenu in the People section.
  html_source->AddBoolean("isAccountManagerEnabled",
                          account_manager_ != nullptr);
  html_source->AddBoolean("isDeviceAccountManaged",
                          profile()->GetProfilePolicyConnector()->IsManaged());

  html_source->AddBoolean(
      "secondaryGoogleAccountSigninAllowed",
      pref_service_->GetBoolean(
          ::account_manager::prefs::kSecondaryGoogleAccountSigninAllowed));

  html_source->AddBoolean(
      "driveSuggestAvailable",
      base::FeatureList::IsEnabled(omnibox::kDocumentProvider));

  AddAccountManagerPageStrings(html_source, profile());
  AddLockScreenPageStrings(html_source, profile());
  AddFingerprintListStrings(html_source);
  AddFingerprintResources(html_source, AreFingerprintSettingsAllowed());
  AddSetupFingerprintDialogStrings(html_source);
  AddSetupPinDialogStrings(html_source);
  AddUsersStrings(html_source);
  AddParentalControlStrings(html_source,
                            ShouldShowParentalControlSettings(profile()));
  AddGraduationStrings(html_source, profile());

  ::settings::AddPasswordPromptDialogStrings(html_source);
}

void PeopleSection::AddHandlers(content::WebUI* web_ui) {
  web_ui->AddMessageHandler(
      std::make_unique<::settings::PeopleHandler>(profile()));
  web_ui->AddMessageHandler(
      std::make_unique<::settings::ProfileInfoHandler>(profile()));

  if (account_manager_facade_) {
    web_ui->AddMessageHandler(std::make_unique<AccountManagerUIHandler>(
        account_manager_, account_manager_facade_, identity_manager_,
        account_apps_availability_));
  }

  web_ui->AddMessageHandler(
      std::make_unique<QuickUnlockHandler>(profile(), pref_service_));

  web_ui->AddMessageHandler(std::make_unique<FingerprintHandler>(profile()));

  if (!profile()->IsGuestSession() &&
      ShouldShowParentalControlSettings(profile())) {
    web_ui->AddMessageHandler(
        std::make_unique<ParentalControlsHandler>(profile()));
  }
}

int PeopleSection::GetSectionNameMessageId() const {
  return IDS_OS_SETTINGS_PEOPLE_V2;
}

mojom::Section PeopleSection::GetSection() const {
  return mojom::Section::kPeople;
}

mojom::SearchResultIcon PeopleSection::GetSectionIcon() const {
  return mojom::SearchResultIcon::kAvatar;
}

const char* PeopleSection::GetSectionPath() const {
  return mojom::kPeopleSectionPath;
}

bool PeopleSection::LogMetric(mojom::Setting setting,
                              base::Value& value) const {
  switch (setting) {
    case mojom::Setting::kAddAccount:
      base::UmaHistogramCounts1000("ChromeOS.Settings.People.AddAccountCount",
                                   value.GetInt());
      return true;

    default:
      return false;
  }
}

void PeopleSection::RegisterHierarchy(HierarchyGenerator* generator) const {
  generator->RegisterTopLevelSetting(mojom::Setting::kAddAccount);
  generator->RegisterTopLevelSetting(mojom::Setting::kRemoveAccount);
  generator->RegisterTopLevelSetting(mojom::Setting::kSetUpParentalControls);
  generator->RegisterTopLevelSetting(mojom::Setting::kGraduation);

  // Smart Lock -- main setting is on multidevice page, but is mirrored here
  generator->RegisterNestedAltSetting(mojom::Setting::kSmartLockOnOff,
                                      mojom::Subpage::kSecurityAndSignInV2);
}

void PeopleSection::FetchAccounts() {
  CHECK(account_manager_);
  account_manager_->GetAccounts(
      base::BindOnce(&PeopleSection::UpdateAccountManagerSearchTags,
                     weak_factory_.GetWeakPtr()));
}

void PeopleSection::OnTokenUpserted(const ::account_manager::Account& account) {
  FetchAccounts();
}

void PeopleSection::OnAccountRemoved(
    const ::account_manager::Account& account) {
  FetchAccounts();
}

void PeopleSection::UpdateAccountManagerSearchTags(
    const std::vector<::account_manager::Account>& accounts) {
  DCHECK(IsAccountManagerAvailable(profile()));

  // Start with no Account Manager search tags.
  SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate();
  updater.RemoveSearchTags(GetRemoveAccountSearchConcepts());

  user_manager::User* user = ProfileHelper::Get()->GetUserByProfile(profile());
  DCHECK(user);

  for (const ::account_manager::Account& account : accounts) {
    if (IsSameAccount(account.key, user->GetAccountId())) {
      continue;
    }

    // If a non-device account exists, add the "Remove Account" search tag.
    updater.AddSearchTags(GetRemoveAccountSearchConcepts());
    return;
  }
}

bool PeopleSection::AreFingerprintSettingsAllowed() {
  return fp_engine_.IsFingerprintEnabled(
      *profile()->GetPrefs(), LegacyFingerprintEngine::Purpose::kAny);
}

}  // namespace ash::settings
