// Copyright 2022 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/commerce/commerce_ui_tab_helper.h"

#include <memory>

#include "base/check_is_test.h"
#include "base/functional/bind.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/user_metrics.h"
#include "base/metrics/user_metrics_action.h"
#include "base/strings/string_number_conversions.h"
#include "base/time/time.h"
#include "chrome/browser/feature_engagement/non_iph_promo.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/browser_window/public/browser_window_features.h"
#include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
#include "chrome/browser/ui/commerce/commerce_page_action_controller.h"
#include "chrome/browser/ui/commerce/discounts_page_action_controller.h"
#include "chrome/browser/ui/page_action/page_action_icon_type.h"
#include "chrome/browser/ui/side_panel/side_panel_entry.h"
#include "chrome/browser/ui/side_panel/side_panel_entry_key.h"
#include "chrome/browser/ui/side_panel/side_panel_registry.h"
#include "chrome/browser/ui/side_panel/side_panel_ui.h"
#include "chrome/browser/ui/tabs/public/tab_features.h"
#include "chrome/browser/ui/tabs/tab_model.h"
#include "chrome/browser/ui/ui_features.h"
#include "chrome/browser/ui/views/chrome_layout_provider.h"
#include "chrome/browser/ui/views/commerce/discounts_bubble_dialog_view.h"
#include "chrome/browser/ui/views/commerce/discounts_page_action_view_controller.h"
#include "chrome/browser/ui/views/commerce/price_insights_page_action_view_controller.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/frame/toolbar_button_provider.h"
#include "chrome/browser/ui/views/side_panel/side_panel_coordinator.h"
#include "chrome/browser/ui/views/side_panel/side_panel_web_ui_view.h"
#include "chrome/browser/ui/webui/commerce/shopping_insights_side_panel_ui.h"
#include "chrome/common/pref_names.h"
#include "components/bookmarks/browser/bookmark_model.h"
#include "components/commerce/core/commerce_constants.h"
#include "components/commerce/core/commerce_feature_list.h"
#include "components/commerce/core/commerce_utils.h"
#include "components/commerce/core/feature_utils.h"
#include "components/commerce/core/metrics/discounts_metric_collector.h"
#include "components/commerce/core/metrics/metrics_utils.h"
#include "components/commerce/core/price_tracking_utils.h"
#include "components/commerce/core/shopping_service.h"
#include "components/feature_engagement/public/feature_constants.h"
#include "components/image_fetcher/core/image_fetcher.h"
#include "components/strings/grit/components_strings.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_details.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/web_contents.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/models/image_model.h"
#include "ui/views/vector_icons.h"
#include "ui/views/view_class_properties.h"
#include "url/gurl.h"

using SidePanelWebUIViewT_ShoppingInsightsSidePanelUI =
    SidePanelWebUIViewT<ShoppingInsightsSidePanelUI>;
using commerce::metrics::ShoppingContextualFeature;
BEGIN_TEMPLATE_METADATA(SidePanelWebUIViewT_ShoppingInsightsSidePanelUI,
                        SidePanelWebUIViewT)
END_METADATA

namespace commerce {

DEFINE_USER_DATA(CommerceUiTabHelper);

// static
CommerceUiTabHelper* CommerceUiTabHelper::From(tabs::TabModel* tab) {
  return Get(tab->GetUnownedUserDataHost());
}

CommerceUiTabHelper::CommerceUiTabHelper(
    tabs::TabInterface& tab_interface,
    ShoppingService* shopping_service,
    bookmarks::BookmarkModel* model,
    image_fetcher::ImageFetcher* image_fetcher,
    SidePanelRegistry* side_panel_registry)
    : ContentsObservingTabFeature(tab_interface),
      shopping_service_(shopping_service),
      bookmark_model_(model),
      image_fetcher_(image_fetcher),
      side_panel_registry_(side_panel_registry),
      price_insights_label_type_(PriceInsightsIconLabelType::kNone),
      scoped_unowned_user_data_(tab_interface.GetUnownedUserDataHost(), *this) {
  if (!image_fetcher_) {
    CHECK_IS_TEST();
  }

  if (shopping_service_) {
    shopping_service_->WaitForReady(
        base::BindOnce(&CommerceUiTabHelper::UpdateUiForShoppingServiceReady,
                       weak_ptr_factory_.GetWeakPtr()));
  } else {
    CHECK_IS_TEST();
  }

  discounts_page_action_controller_ =
      std::make_unique<DiscountsPageActionController>(
          GetPageActionControllerNotificationCallback(
              base::BindRepeating(&CommerceUiTabHelper::UpdateDiscountsIconView,
                                  weak_ptr_factory_.GetWeakPtr())),
          shopping_service_);

  discounts_bubble_coordinator_ =
      std::make_unique<DiscountsBubbleCoordinator>();
}

CommerceUiTabHelper::~CommerceUiTabHelper() = default;

// static
void CommerceUiTabHelper::RegisterProfilePrefs(PrefRegistrySimple* registry) {
  registry->RegisterBooleanPref(prefs::kShouldShowPriceTrackFUEBubble, true);
}

void CommerceUiTabHelper::UpdateUiForShoppingServiceReady(
    ShoppingService* service) {
  // This will happen in tests that don't pass CHECK_IS_TEST.
  if (!service) {
    return;
  }

  if (commerce::IsPriceInsightsEligible(service->GetAccountChecker())) {
    UpdatePriceInsightsIconView();
  }
}

void CommerceUiTabHelper::DidFinishNavigation(
    content::NavigationHandle* navigation_handle) {
  if (!navigation_handle->IsInPrimaryMainFrame() ||
      ShouldIgnoreSameUrlNavigation() ||
      IsSameDocumentWithSameCommittedUrl(navigation_handle)) {
    is_initial_navigation_committed_ = true;
    return;
  }

  // The page action icon may not have been used for the last page load. If
  // that's the case, make sure we record it.
  RecordPriceInsightsIconMetrics(/*from_icon_use=*/false);

  previous_main_frame_url_ = navigation_handle->GetURL();
  product_info_for_page_.reset();
  is_page_action_expansion_computed_for_page_ = false;
  got_discounts_response_for_page_ = false;
  got_insights_response_for_page_ = false;
  page_has_discounts_ = false;
  page_action_to_expand_ = std::nullopt;
  page_action_expanded_ = std::nullopt;
  pending_tracking_state_.reset();
  price_insights_info_.reset();
  icon_use_recorded_for_page_.clear();
  price_insights_label_type_ = PriceInsightsIconLabelType::kNone;

  MakeShoppingInsightsSidePanelUnavailable();

  if (!shopping_service_) {
    return;
  }

  page_action_icon_compute_start_time_ = base::TimeTicks::Now();

  discounts_page_action_controller_->ResetForNewNavigation(
      web_contents()->GetLastCommittedURL());

  // This value should not be a class member variable as it might change within
  // a browser session.
  bool is_price_insights_eligible =
      commerce::IsPriceInsightsEligible(shopping_service_->GetAccountChecker());
  if (is_price_insights_eligible) {
    UpdatePriceInsightsIconView();
  }

  if (is_price_insights_eligible) {
    // Price insights needs product info to get the product cluster title.
    shopping_service_->GetProductInfoForUrl(
        web_contents()->GetLastCommittedURL(),
        base::BindOnce(&CommerceUiTabHelper::HandleProductInfoResponse,
                       weak_ptr_factory_.GetWeakPtr()));
  }
}

bool CommerceUiTabHelper::ShouldIgnoreSameUrlNavigation() {
  return previous_main_frame_url_ == web_contents()->GetLastCommittedURL() &&
         is_initial_navigation_committed_;
}

bool CommerceUiTabHelper::IsSameDocumentWithSameCommittedUrl(
    content::NavigationHandle* navigation_handle) {
  return previous_main_frame_url_ == web_contents()->GetLastCommittedURL() &&
         navigation_handle->IsSameDocument();
}

void CommerceUiTabHelper::WebContentsDestroyed() {
  // If the tab or browser is closed, try recording whether the price tracking
  // icon was used.
  RecordPriceInsightsIconMetrics(/*from_icon_use=*/false);
}

void CommerceUiTabHelper::TriggerUpdateForIconView() {
  if (!shopping_service_) {
    return;
  }

  if (commerce::IsPriceInsightsEligible(
          shopping_service_->GetAccountChecker())) {
    UpdatePriceInsightsIconView();
  }
}

void CommerceUiTabHelper::UpdatePriceInsightsIconView() {
  PriceInsightsPageActionViewController::From(tab())->UpdatePageActionIcon(
      ShouldShowPriceInsightsIconView(),
      ShouldExpandPageActionIcon(PageActionIconType::kPriceInsights),
      GetPriceInsightsIconLabelTypeForPage());
}

void CommerceUiTabHelper::SetImageFetcherForTesting(
    image_fetcher::ImageFetcher* image_fetcher) {
  CHECK_IS_TEST();
  image_fetcher_ = image_fetcher;
}

bool CommerceUiTabHelper::ShouldShowDiscountsIconView() {
  return discounts_page_action_controller_->ShouldShowForNavigation().value_or(
      false);
}

bool CommerceUiTabHelper::ShouldShowPriceInsightsIconView() {
  return shopping_service_ &&
         commerce::IsPriceInsightsEligible(
             shopping_service_->GetAccountChecker()) &&
         price_insights_info_.has_value();
}

void CommerceUiTabHelper::HandleProductInfoResponse(
    const GURL& url,
    const std::optional<const ProductInfo>& info) {
  if (url != web_contents()->GetLastCommittedURL() || !info.has_value()) {
    // Price insights is depended on ProductInfo, it's impossible to get
    // insights without it.
    got_insights_response_for_page_ = true;
    MaybeComputePageActionToExpand();
    return;
  }

  product_info_for_page_ = info;

  if (commerce::IsPriceInsightsEligible(
          shopping_service_->GetAccountChecker())) {
    if (!info->product_cluster_title.empty()) {
      shopping_service_->GetPriceInsightsInfoForUrl(
          url,
          base::BindOnce(&CommerceUiTabHelper::HandlePriceInsightsInfoResponse,
                         weak_ptr_factory_.GetWeakPtr()));
    } else {
      // If we were blocked because of the title, consider it a response of
      // false.
      got_insights_response_for_page_ = true;
    }
  }
}

void CommerceUiTabHelper::HandlePriceInsightsInfoResponse(
    const GURL& url,
    const std::optional<PriceInsightsInfo>& info) {
  got_insights_response_for_page_ = true;

  if (url != web_contents()->GetLastCommittedURL() || !info.has_value()) {
    MaybeComputePageActionToExpand();
    return;
  }

  price_insights_info_.emplace(info.value());
  MaybeComputePageActionToExpand();
  MakeShoppingInsightsSidePanelAvailable();
  TriggerUpdateForIconView();
}

void CommerceUiTabHelper::MaybeComputePageActionToExpand() {
  if (!shopping_service_) {
    return;
  }

  // Make sure we have responses from all the relevant features first.
  if (!discounts_page_action_controller_->ShouldShowForNavigation()
           .has_value()) {
    return;
  }

  if (commerce::IsPriceInsightsEligible(
          shopping_service_->GetAccountChecker()) &&
      !got_insights_response_for_page_) {
    return;
  }

  if (is_page_action_expansion_computed_for_page_) {
    return;
  }

  ComputePageActionToExpand();

  is_page_action_expansion_computed_for_page_ = true;

  if (ShouldShowPriceInsightsIconView()) {
    base::UmaHistogramEnumeration("Commerce.PriceInsights.OmniboxIconShown",
                                  price_insights_label_type_);
  }

  UpdateDiscountsIconView();
  UpdatePriceInsightsIconView();

  if (ShouldShowDiscountsIconView()) {
    commerce::metrics::DiscountsMetricCollector::
        RecordDiscountsPageActionIconExpandState(
            IsPageActionIconExpanded(PageActionIconType::kDiscounts),
            GetDiscounts());
  }
}

void CommerceUiTabHelper::SetPriceTrackingState(
    bool enable,
    bool is_new_bookmark,
    base::OnceCallback<void(bool)> callback) {
  const bookmarks::BookmarkNode* node =
      bookmark_model_->GetMostRecentlyAddedUserNodeForURL(
          web_contents()->GetLastCommittedURL());

  base::OnceCallback<void(bool)> wrapped_callback = base::BindOnce(
      [](base::WeakPtr<CommerceUiTabHelper> helper,
         base::OnceCallback<void(bool)> callback, bool is_tracked,
         bool success) {
        if (helper) {
          helper->pending_tracking_state_.reset();
        }

        std::move(callback).Run(success);
      },
      weak_ptr_factory_.GetWeakPtr(), std::move(callback), enable);

  pending_tracking_state_.emplace(enable);

  if (node) {
    commerce::SetPriceTrackingStateForBookmark(
        shopping_service_.get(), bookmark_model_.get(), node, enable,
        std::move(wrapped_callback), enable && is_new_bookmark);
  } else {
    DCHECK(!enable);
    std::optional<commerce::ProductInfo> info =
        shopping_service_->GetAvailableProductInfoForUrl(
            web_contents()->GetLastCommittedURL());
    if (info.has_value()) {
      commerce::SetPriceTrackingStateForClusterId(
          shopping_service_.get(), bookmark_model_,
          info->product_cluster_id.value(), enable,
          std::move(wrapped_callback));
    }
  }
}

void CommerceUiTabHelper::OnPriceInsightsIconClicked() {
  auto* side_panel_ui = GetSidePanelUI();
  DCHECK(side_panel_ui);
  SidePanelEntry* const entry = side_panel_registry_->GetEntryForKey(
      SidePanelEntryKey(SidePanelEntry::Id::kShoppingInsights));
  DCHECK(entry);

  if (side_panel_ui->IsSidePanelEntryShowing(
          SidePanelEntryKey(SidePanelEntryId::kShoppingInsights))) {
    side_panel_ui->Close();
  } else {
    side_panel_ui->Show(SidePanelEntryId::kShoppingInsights);
    if (price_insights_info_.has_value()) {
      base::UmaHistogramEnumeration("Commerce.PriceInsights.OmniboxIconClicked",
                                    price_insights_label_type_);
      base::UmaHistogramBoolean(
          "Commerce.PriceInsights.SidePanelOpenWithMultipleCatalogs",
          price_insights_info_->has_multiple_catalogs);
      commerce::metrics::RecordShoppingActionUKM(
          web_contents()->GetPrimaryMainFrame()->GetPageUkmSourceId(),
          commerce::metrics::ShoppingAction::kPriceInsightsOpened);
    }
  }
  RecordPriceInsightsIconMetrics(true);
}

const std::vector<DiscountInfo>& CommerceUiTabHelper::GetDiscounts() {
  return discounts_page_action_controller_->GetDiscounts();
}

void CommerceUiTabHelper::MakeShoppingInsightsSidePanelAvailable() {
  auto entry = std::make_unique<SidePanelEntry>(
      SidePanelEntry::Key(SidePanelEntry::Id::kShoppingInsights),
      base::BindRepeating(&CommerceUiTabHelper::CreateShoppingInsightsWebView,
                          base::Unretained(this)),
      /*default_content_width_callback=*/base::NullCallback());
  side_panel_registry_->Register(std::move(entry));
}

void CommerceUiTabHelper::MakeShoppingInsightsSidePanelUnavailable() {
  SidePanelEntry* const entry = side_panel_registry_->GetEntryForKey(
      SidePanelEntryKey(SidePanelEntry::Id::kShoppingInsights));

  if (!entry) {
    return;
  }

  auto* side_panel_ui = GetSidePanelUI();
  if (side_panel_ui && side_panel_ui->IsSidePanelEntryShowing(entry->key())) {
    side_panel_ui->Close();
    base::RecordAction(base::UserMetricsAction(
        "Commerce.PriceInsights.NavigationClosedSidePanel"));
  }

  side_panel_registry_->Deregister(entry->key());
}

std::unique_ptr<views::View> CommerceUiTabHelper::CreateShoppingInsightsWebView(
    SidePanelEntryScope& scope) {
  auto shopping_insights_web_view =
      std::make_unique<SidePanelWebUIViewT<ShoppingInsightsSidePanelUI>>(
          scope, base::RepeatingClosure(), base::RepeatingClosure(),
          std::make_unique<WebUIContentsWrapperT<ShoppingInsightsSidePanelUI>>(
              GURL(kChromeUIShoppingInsightsSidePanelUrl),
              Profile::FromBrowserContext(web_contents()->GetBrowserContext()),
              IDS_SHOPPING_INSIGHTS_SIDE_PANEL_TITLE,
              /*esc_closes_ui=*/false));
  // Call ShowUI() to make the UI ready, this doesn't really open/switch the
  // side panel.
  shopping_insights_web_view->ShowUI();

  return shopping_insights_web_view;
}

SidePanelUI* CommerceUiTabHelper::GetSidePanelUI() {
  if (BrowserWindowInterface* bwi = tab().GetBrowserWindowInterface()) {
    return bwi->GetFeatures().side_panel_ui();
  }

  return nullptr;
}

const std::optional<bool>&
CommerceUiTabHelper::GetPendingTrackingStateForTesting() {
  return pending_tracking_state_;
}

const std::optional<PriceInsightsInfo>&
CommerceUiTabHelper::GetPriceInsightsInfo() {
  return price_insights_info_;
}

void CommerceUiTabHelper::ShowDiscountBubble(
    const DiscountInfo& discount,
    base::OnceClosure one_bubble_closing_callback) {
  discounts_bubble_coordinator_->Show(GetDiscountsBubbleAnchor(),
                                      tab().GetContents(), discount,
                                      std::move(one_bubble_closing_callback));
}

void CommerceUiTabHelper::UpdateDiscountsIconView() {
  DiscountsPageActionViewController::From(tab())->UpdatePageIcon(
      ShouldShowDiscountsIconView(),
      ShouldExpandPageActionIcon(PageActionIconType::kDiscounts));
}

const DiscountsBubbleCoordinator&
CommerceUiTabHelper::GetDiscountsBubbleCoordinator() const {
  return *discounts_bubble_coordinator_;
}

views::BubbleAnchor CommerceUiTabHelper::GetDiscountsBubbleAnchor() {
  BrowserWindowInterface* bwi = tab().GetBrowserWindowInterface();
  CHECK(bwi);

  // TODO(https://crbug.com/425953501): Remove GetBrowserForMigrationOnly since
  // Browser* will not be needed once ToolBarButtonProvider is migrated to
  // BrowserWindowInterface.
  auto* browser_view =
      BrowserView::GetBrowserViewForBrowser(bwi->GetBrowserForMigrationOnly());
  if (!browser_view) {
    return views::BubbleAnchor();
  }

  auto* toolbar_button_provider = browser_view->toolbar_button_provider();
  if (!toolbar_button_provider) {
    return views::BubbleAnchor();
  }

  return toolbar_button_provider->GetPageActionBubbleAnchor(
      kActionCommerceDiscounts);
}

void CommerceUiTabHelper::ComputePageActionToExpand() {
  if (!page_action_icon_compute_start_time_.is_null()) {
    base::UmaHistogramTimes(
        "Commerce.IconComputationTime",
        base::TimeTicks::Now() - page_action_icon_compute_start_time_);
    page_action_to_expand_ = std::nullopt;
  }

  page_action_icon_compute_start_time_ = base::TimeTicks();

  if (!web_contents() || !web_contents()->GetBrowserContext()) {
    page_action_to_expand_ = std::nullopt;
    return;
  }

  // TODO(b:301440117): Splitting the triggering logic for each icon into
  //                    delegates would make this much easier to test.
  if (discounts_page_action_controller_->WantsExpandedUi()) {
    page_action_to_expand_ = PageActionIconType::kDiscounts;
    MaybeRecordShoppingInformationUKM(PageActionIconType::kDiscounts);
    return;
  }

  // Prioritize the price insights icon.
  if (ShouldShowPriceInsightsIconView()) {
    PriceInsightsIconLabelType label_type =
        GetPriceInsightsIconLabelTypeForPage();
    bool icon_has_label = label_type != PriceInsightsIconLabelType::kNone;

    if (icon_has_label &&
        feature_engagement::NonIphPromo::RequestPermissionToShow(
            web_contents()->GetBrowserContext(),
            feature_engagement::kIPHPriceInsightsPageActionIconLabelFeature)) {
      page_action_to_expand_ = PageActionIconType::kPriceInsights;
      MaybeRecordShoppingInformationUKM(PageActionIconType::kPriceInsights);
      price_insights_label_type_ = label_type;
      return;
    }
  }

  MaybeRecordShoppingInformationUKM(std::nullopt);
}

PriceInsightsIconLabelType
CommerceUiTabHelper::GetPriceInsightsIconLabelTypeForPage() {
  auto& price_insights_info = GetPriceInsightsInfo();

  if (!price_insights_info.has_value() ||
      !price_insights_info->typical_low_price_micros.has_value() ||
      !price_insights_info->typical_high_price_micros.has_value() ||
      price_insights_info->catalog_history_prices.empty()) {
    return PriceInsightsIconLabelType::kNone;
  } else if (price_insights_info->price_bucket ==
             commerce::PriceBucket::kLowPrice) {
    return PriceInsightsIconLabelType::kPriceIsLow;
  } else if (price_insights_info->price_bucket ==
                 commerce::PriceBucket::kHighPrice &&
             commerce::kPriceInsightsChipLabelExpandOnHighPrice.Get()) {
    return PriceInsightsIconLabelType::kPriceIsHigh;
  } else {
    return PriceInsightsIconLabelType::kNone;
  }
}

bool CommerceUiTabHelper::ShouldExpandPageActionIcon(PageActionIconType type) {
  // Only allow the requesting icon to expand once. This prevents the icon from
  // expanding multiple times per page load.
  if (page_action_to_expand_.has_value() &&
      type == page_action_to_expand_.value()) {
    page_action_expanded_ = page_action_to_expand_.value();
    page_action_to_expand_ = std::nullopt;
    return true;
  }
  return false;
}

bool CommerceUiTabHelper::IsPageActionIconExpanded(PageActionIconType type) {
  return page_action_expanded_.has_value() &&
         type == page_action_expanded_.value();
}

void CommerceUiTabHelper::OnDiscountsCouponCodeCopied() {
  discounts_page_action_controller_->CouponCodeCopied();
}

bool CommerceUiTabHelper::IsDiscountsCouponCodeCopied() {
  return discounts_page_action_controller_->IsCouponCodeCopied();
}

bool CommerceUiTabHelper::ShouldAutoShowDiscountsBubble(uint64_t discount_id,
                                                        bool is_merchant_wide) {
  return discounts_page_action_controller_->ShouldAutoShowBubble(
      discount_id, is_merchant_wide);
}

void CommerceUiTabHelper::DiscountsBubbleShown(uint64_t discount_id) {
  discounts_page_action_controller_->DiscountsBubbleShown(discount_id);
}

void CommerceUiTabHelper::RecordIconMetrics(PageActionIconType page_action,
                                            bool from_icon_use) {
  if (icon_use_recorded_for_page_.contains(page_action)) {
    return;
  }
  icon_use_recorded_for_page_.insert(page_action);

  std::string histogram_name;
  switch (page_action) {
    case PageActionIconType::kPriceInsights:
      histogram_name = "Commerce.PriceInsights.IconInteractionState";
      break;
    default:
      return;
  }

  bool expanded = page_action_expanded_.has_value() &&
                  page_action_expanded_.value() == page_action;

  if (from_icon_use) {
    if (expanded) {
      base::UmaHistogramEnumeration(
          histogram_name, PageActionIconInteractionState::kClickedExpanded);
    } else {
      base::UmaHistogramEnumeration(histogram_name,
                                    PageActionIconInteractionState::kClicked);
    }
  } else {
    if (expanded) {
      base::UmaHistogramEnumeration(
          histogram_name, PageActionIconInteractionState::kNotClickedExpanded);
    } else {
      base::UmaHistogramEnumeration(
          histogram_name, PageActionIconInteractionState::kNotClicked);
    }
  }
}

void CommerceUiTabHelper::RecordPriceInsightsIconMetrics(bool from_icon_use) {
  if (ShouldShowPriceInsightsIconView()) {
    RecordIconMetrics(PageActionIconType::kPriceInsights, from_icon_use);
  }
}

void CommerceUiTabHelper::MaybeRecordShoppingInformationUKM(
    std::optional<PageActionIconType> page_action_type) {
  // This is our current definition of shopping content.
  if (!product_info_for_page_.has_value()) {
    return;
  }

  auto ukm_builder = ukm::builders::Shopping_ShoppingInformation(
      web_contents()->GetPrimaryMainFrame()->GetPageUkmSourceId());

  if (page_action_type.has_value()) {
    int64_t promoted_feature = 0;
    if (page_action_type == PageActionIconType::kDiscounts) {
      promoted_feature =
          static_cast<int64_t>(ShoppingContextualFeature::kDiscounts);
    } else if (page_action_type == PageActionIconType::kPriceInsights) {
      promoted_feature =
          static_cast<int64_t>(ShoppingContextualFeature::kPriceInsights);
    } else {
      NOTREACHED();
    }
    ukm_builder.SetPromotedFeature(promoted_feature);
  }

  ukm_builder.SetHasPriceInsights(price_insights_info_.has_value())
      .SetHasDiscount(
          discounts_page_action_controller_->ShouldShowForNavigation().value_or(
              false))
      .SetIsPriceTrackable(true)
      .SetIsShoppingContent(true)
      .Record(ukm::UkmRecorder::Get());
}

void CommerceUiTabHelper::OnPageActionControllerNotification(
    base::RepeatingClosure page_action_icon_update_callback) {
  MaybeComputePageActionToExpand();
  page_action_icon_update_callback.Run();
}

base::RepeatingClosure
CommerceUiTabHelper::GetPageActionControllerNotificationCallback(
    base::RepeatingClosure page_action_icon_update_callback) {
  return base::BindRepeating(
      &CommerceUiTabHelper::OnPageActionControllerNotification,
      weak_ptr_factory_.GetWeakPtr(),
      std::move(page_action_icon_update_callback));
}



}  // namespace commerce
