// 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 "components/commerce/core/metrics/metrics_utils.h"

#include "base/metrics/histogram_functions.h"
#include "components/commerce/core/account_checker.h"
#include "components/commerce/core/commerce_feature_list.h"
#include "components/commerce/core/proto/price_tracking.pb.h"
#include "components/optimization_guide/core/hints/optimization_guide_decision.h"
#include "components/optimization_guide/core/optimization_guide_permissions_util.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "url/gurl.h"

namespace commerce::metrics {

const char kPDPNavShoppingListEligibleHistogramName[] =
    "Commerce.PDPNavigation.ShoppingList.Eligible";
const char kPDPStateHistogramName[] = "Commerce.PDPStateOnNavigation";
const char kPDPStateWithLocalMetaName[] = "Commerce.PDPStateWithLocalMeta";
const char kShoppingListIneligibleHistogramName[] =
    "Commerce.PDPNavigation.ShoppingList.IneligibilityReason";
const char kPDPNavURLSize[] = "Commerce.PDPNavigation.URLSize";

void RecordPDPStateToUma(ShoppingPDPState state) {
  base::UmaHistogramEnumeration(kPDPStateHistogramName, state);
}

void RecordPDPNavShoppingListEligible(ShoppingPDPState state,
                                      bool is_shopping_list_eligible) {
  // Only record this metric for pages that were determined to be PDPs.
  if (state == ShoppingPDPState::kNotPDP) {
    return;
  }

  base::UmaHistogramBoolean(kPDPNavShoppingListEligibleHistogramName,
                            is_shopping_list_eligible);
}

void RecordUrlSizeforPDP(
    optimization_guide::OptimizationGuideDecision decision,
    const optimization_guide::OptimizationMetadata& metadata,
    const GURL& url) {
  if (decision != optimization_guide::OptimizationGuideDecision::kTrue ||
      !metadata.any_metadata().has_value()) {
    return;
  }
  base::UmaHistogramCounts10000(kPDPNavURLSize, url.spec().size());
}

ShoppingPDPState ComputeStateForOptGuideResult(
    optimization_guide::OptimizationGuideDecision decision,
    const optimization_guide::OptimizationMetadata& metadata) {
  if (decision != optimization_guide::OptimizationGuideDecision::kTrue ||
      !metadata.any_metadata().has_value()) {
    return ShoppingPDPState::kNotPDP;
  }

  std::optional<PriceTrackingData> parsed_any =
      optimization_guide::ParsedAnyMetadata<PriceTrackingData>(
          metadata.any_metadata().value());

  if (!parsed_any.has_value() || !parsed_any.value().IsInitialized())
    return ShoppingPDPState::kNotPDP;

  const PriceTrackingData& price_data = parsed_any.value();

  if (price_data.has_buyable_product() &&
      price_data.buyable_product().has_product_cluster_id()) {
    return ShoppingPDPState::kIsPDPWithClusterId;
  }

  return ShoppingPDPState::kIsPDPWithoutClusterId;
}

void RecordPDPMetrics(optimization_guide::OptimizationGuideDecision decision,
                      const optimization_guide::OptimizationMetadata& metadata,
                      PrefService* pref_service,
                      bool is_off_the_record,
                      bool is_shopping_list_eligible,
                      const GURL& url) {
  // If optimization guide isn't allowed to run, don't attempt to query and
  // record the metrics.
  if (!pref_service ||
      !optimization_guide::IsUserPermittedToFetchFromRemoteOptimizationGuide(
          is_off_the_record, pref_service)) {
    return;
  }

  ShoppingPDPState state = ComputeStateForOptGuideResult(decision, metadata);

  RecordPDPStateToUma(state);
  RecordPDPNavShoppingListEligible(state, is_shopping_list_eligible);
  RecordUrlSizeforPDP(decision, metadata, url);
}

void RecordPDPStateWithLocalMeta(bool detected_by_server,
                                 bool detected_by_client,
                                 ukm::SourceId source_id) {
  ShoppingPDPDetectionMethod detection_method =
      ShoppingPDPDetectionMethod::kNotPDP;
  if (detected_by_server && detected_by_client) {
    detection_method = ShoppingPDPDetectionMethod::kPDPServerAndLocalMeta;
  } else if (detected_by_server) {
    detection_method = ShoppingPDPDetectionMethod::kPDPServerOnly;
  } else if (detected_by_client) {
    detection_method = ShoppingPDPDetectionMethod::kPDPLocalMetaOnly;
  }

  base::UmaHistogramEnumeration(kPDPStateWithLocalMetaName, detection_method);

  ukm::builders::Shopping_PDPStateWithLocalInfo(source_id)
      .SetPDPState(static_cast<int64_t>(detection_method))
      .Record(ukm::UkmRecorder::Get());
}

void RecordShoppingListIneligibilityReasons(
    PrefService* pref_service,
    commerce::AccountChecker* account_checker,
    bool is_off_the_record,
    bool supported_country) {
  if (!supported_country) {
    base::UmaHistogramEnumeration(
        kShoppingListIneligibleHistogramName,
        ShoppingFeatureIneligibilityReason::kUnsupportedCountryOrLocale);
  }

  if (!IsShoppingListAllowedForEnterprise(pref_service)) {
    base::UmaHistogramEnumeration(
        kShoppingListIneligibleHistogramName,
        ShoppingFeatureIneligibilityReason::kEnterprisePolicy);
  }

  if (!account_checker->IsSignedIn()) {
    base::UmaHistogramEnumeration(kShoppingListIneligibleHistogramName,
                                  ShoppingFeatureIneligibilityReason::kSignin);
  }

  if (!account_checker->IsSyncTypeEnabled(
          syncer::UserSelectableType::kBookmarks)) {
    base::UmaHistogramEnumeration(kShoppingListIneligibleHistogramName,
                                  ShoppingFeatureIneligibilityReason::kSync);
  }

  if (!account_checker->IsAnonymizedUrlDataCollectionEnabled()) {
    base::UmaHistogramEnumeration(kShoppingListIneligibleHistogramName,
                                  ShoppingFeatureIneligibilityReason::kMSBB);
  }

  if (account_checker->IsSubjectToParentalControls()) {
    base::UmaHistogramEnumeration(
        kShoppingListIneligibleHistogramName,
        ShoppingFeatureIneligibilityReason::kParentalControls);
  }
}

void RecordShoppingActionUKM(ukm::SourceId ukm_source_id,
                             ShoppingAction action) {
  auto ukm_builder = ukm::builders::Shopping_ShoppingAction(ukm_source_id);
  switch (action) {
    case ShoppingAction::kDiscountCopied:
      ukm_builder.SetDiscountCopied(true);
      break;
    case ShoppingAction::kDiscountOpened:
      ukm_builder.SetDiscountOpened(true);
      break;
    case ShoppingAction::kPriceInsightsOpened:
      ukm_builder.SetPriceInsightsOpened(true);
      break;
    case ShoppingAction::kPriceTracked:
      ukm_builder.SetPriceTracked(true);
      break;
    default:
      NOTREACHED();
  }
  ukm_builder.Record(ukm::UkmRecorder::Get());
}
}  // namespace commerce::metrics
