// Copyright 2025 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/views/user_education/browser_ntp_promos.h"

#include "base/functional/callback_helpers.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search/background/ntp_custom_background_service.h"
#include "chrome/browser/search/background/ntp_custom_background_service_factory.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/signin/signin_promo_util.h"
#include "chrome/browser/signin/signin_ui_util.h"
#include "chrome/browser/signin/signin_util.h"
#include "chrome/browser/themes/theme_service.h"
#include "chrome/browser/themes/theme_service_factory.h"
#include "chrome/browser/ui/actions/chrome_action_id.h"
#include "chrome/browser/ui/browser_actions.h"
#include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
#include "chrome/browser/ui/navigator/browser_navigator.h"
#include "chrome/browser/ui/navigator/browser_navigator_params.h"
#include "chrome/browser/ui/side_panel/side_panel_action_callback.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/user_education/impl/browser_user_education_context.h"
#include "chrome/browser/user_education/ntp_promo_identifiers.h"
#include "chrome/grit/branded_strings.h"
#include "chrome/grit/generated_resources.h"
#include "components/prefs/pref_service.h"
#include "components/signin/public/base/signin_pref_names.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "components/user_education/common/ntp_promo/ntp_promo_registry.h"
#include "components/user_education/common/ntp_promo/ntp_promo_specification.h"
#include "components/user_education/common/user_education_features.h"
#include "components/user_education/common/user_education_metadata.h"
#include "extensions/browser/extension_util.h"
#include "extensions/common/extension_urls.h"
#include "ui/actions/actions.h"

using user_education::NtpPromoContent;
using user_education::NtpPromoSpecification;

namespace {

using ContextPtr = const user_education::UserEducationContextPtr&;

Profile* GetProfile(ContextPtr context) {
  return context->AsA<BrowserUserEducationContext>()
      ->GetBrowserView()
      .GetProfile();
}

NtpPromoSpecification::Eligibility CheckExtensionsPromoEligibility(
    ContextPtr context) {
  // TODO(webium): add user education context for WebUI browser.
  if (!context) {
    return NtpPromoSpecification::Eligibility::kIneligible;
  }
  return extensions::util::AnyCurrentlyInstalledExtensionIsFromWebstore(
             GetProfile(context))
             ? NtpPromoSpecification::Eligibility::kCompleted
             : NtpPromoSpecification::Eligibility::kEligible;
}

void InvokeExtensionsPromo(ContextPtr context) {
  std::string_view utm_source;
  switch (user_education::features::GetNtpBrowserPromoType()) {
    case user_education::features::NtpBrowserPromoType::kSimple:
      utm_source = extension_urls::kNtpPromo1pUtmSource;
      break;
    default:
      NOTREACHED();
  }

  GURL url_with_utm = extension_urls::AppendUtmSource(
      extension_urls::GetWebstoreLaunchURL(), utm_source);

  // TODO(crbug.com/443062679): Use the BrowserWindowInterface version when
  // it becomes available.
  NavigateParams params(
      context->AsA<BrowserUserEducationContext>()->GetBrowserView().browser(),
      url_with_utm, ui::PAGE_TRANSITION_LINK);
  params.disposition = WindowOpenDisposition::CURRENT_TAB;
  Navigate(&params);
}

NtpPromoSpecification::Eligibility CheckCustomizationPromoEligibility(
    ContextPtr context) {
  // TODO(webium): add user education context for WebUI browser.
  if (!context) {
    return NtpPromoSpecification::Eligibility::kIneligible;
  }
  auto* profile = GetProfile(context);
  auto* background_service =
      NtpCustomBackgroundServiceFactory::GetForProfile(profile);
  auto* theme_service = ThemeServiceFactory::GetForProfile(profile);
  if (!background_service || !theme_service) {
    return NtpPromoSpecification::Eligibility::kIneligible;
  }
  // Infer that if a custom background or theme is used, customization has
  // taken place.
  const bool customized =
      background_service->GetCustomBackground().has_value() ||
      (theme_service->GetThemeID() != ThemeHelper::kDefaultThemeID);
  return customized ? NtpPromoSpecification::Eligibility::kCompleted
                    : NtpPromoSpecification::Eligibility::kEligible;
}

void InvokeCustomizationPromo(ContextPtr context) {
  actions::ActionManager::Get()
      .FindAction(kActionSidePanelShowCustomizeChrome,
                  BrowserActions::From(
                      context->AsA<BrowserUserEducationContext>()->GetBrowser())
                      ->root_action_item())
      ->InvokeAction(
          actions::ActionInvocationContext::Builder()
              .SetProperty(kSidePanelOpenTriggerKey,
                           SidePanelOpenTrigger::kNewTabPageCustomizationPromo)
              .Build());
}

}  // namespace

void MaybeRegisterNtpPromos(user_education::NtpPromoRegistry& registry) {
  if (registry.AreAnyPromosRegistered()) {
    return;
  }

  // Register NTP Promos below.
  //
  // Absent MRU/LRU and explicit `show_after` parameters, promos will be shown
  // in the order they appear here, so pay careful attention to what order new
  // users should see promos in (especially as not all promos may be able to
  // display at once).
  //
  // NOTE: Changes to this file should be reviewed by both a User Education
  // owner (//components/user_education/OWNERS) and an NTP owner
  // (//components/search/OWNERS).

  registry.AddPromo(NtpPromoSpecification(
      kNtpCustomizationPromoId,
      NtpPromoContent("palette-custom", IDS_NTP_CUSTOMIZATION_PROMO,
                      IDS_NTP_CUSTOMIZATION_PROMO),
      base::BindRepeating(&CheckCustomizationPromoEligibility),
      /*show_callback=*/base::DoNothing(),
      base::BindRepeating(&InvokeCustomizationPromo),
      /*show_after=*/{},
      user_education::Metadata(141, "cjgrant@google.com",
                               "Promotes customization of the New Tab Page")));

  registry.AddPromo(NtpPromoSpecification(
      kNtpExtensionsPromoId,
      NtpPromoContent("my-extensions-custom", IDS_NTP_EXTENSIONS_PROMO,
                      IDS_NTP_EXTENSIONS_PROMO),
      base::BindRepeating(&CheckExtensionsPromoEligibility),
      /*show_callback=*/base::DoNothing(),
      base::BindRepeating(&InvokeExtensionsPromo),
      /*show_after=*/{},
      user_education::Metadata(
          141, "cjgrant@google.com",
          "Promotes Chrome extensions on the New Tab Page")));
}
