// 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.

#import "ios/chrome/browser/intelligence/bwg/metrics/gemini_metrics.h"

#import "base/metrics/histogram_functions.h"
#import "base/metrics/user_metrics.h"
#import "base/metrics/user_metrics_action.h"
#import "components/optimization_guide/core/hints/optimization_guide_decision.h"
#import "ios/chrome/browser/intelligence/bwg/utils/gemini_constants.h"
#import "ios/public/provider/chrome/browser/bwg/gemini_api.h"

namespace {
// Minimum time between FRE entry point impression logs.
const base::TimeDelta kGeminiImpressionThrottleInterval = base::Minutes(10);

// Returns the last impression time, persisting within the app session.
base::TimeTicks& GetLastGeminiImpressionTime() {
  static base::TimeTicks last_impression_time;
  return last_impression_time;
}

// Returns an IOSGeminiAspectRatioBucket for a given aspect ratio.
IOSGeminiAspectRatioBucket GetAspectRatioBucket(double aspect_ratio) {
  if (aspect_ratio <= 0) {
    return IOSGeminiAspectRatioBucket::kUnknown;
  }
  if (aspect_ratio < 0.3) {
    return IOSGeminiAspectRatioBucket::kVeryTall;
  }
  if (aspect_ratio < 0.8) {
    return IOSGeminiAspectRatioBucket::kTall;
  }
  if (aspect_ratio < 1.0) {
    return IOSGeminiAspectRatioBucket::kSlightlyTall;
  }
  if (aspect_ratio == 1.0) {
    return IOSGeminiAspectRatioBucket::kPerfectSquare;
  }
  if (aspect_ratio <= 1.2) {
    return IOSGeminiAspectRatioBucket::kSlightlyWide;
  }
  if (aspect_ratio <= 1.7) {
    return IOSGeminiAspectRatioBucket::kWide;
  }
  return IOSGeminiAspectRatioBucket::kVeryWide;
}

}  // namespace

namespace gemini {
IneligibilityReasons& IneligibilityReasons::set_workspace(bool value) {
  workspace = value;
  return *this;
}

IneligibilityReasons& IneligibilityReasons::set_chrome_enterprise(bool value) {
  chrome_enterprise = value;
  return *this;
}

IneligibilityReasons& IneligibilityReasons::set_account_capability(bool value) {
  account_capability = value;
  return *this;
}

IneligibilityReasons& IneligibilityReasons::set_authentication(bool value) {
  authentication = value;
  return *this;
}
}  // namespace gemini

const char kEligibilityHistogram[] = "IOS.Gemini.Eligibility";

const char kEntryPointHistogram[] = "IOS.Gemini.EntryPoint";

const char kSignInRequiredSnackbarShownHistogram[] =
    "IOS.Gemini.SignInRequiredSnackbarShown";

const char kEntryPointImpressionHistogram[] =
    "IOS.Gemini.EntryPoint.Impression";

const char kEntryPointAvailableHistogram[] = "IOS.Gemini.EntryPoint.Available";

const char kFeedbackHistogram[] = "IOS.Gemini.Feedback";

const char kImageActionButtonHistogram[] = "IOS.Gemini.ImageActionButton";

const char kInputPlateAttachmentOptionHistogram[] =
    "IOS.Gemini.InputPlateAttachmentOption";

const char kFirstRunEntryPointHistogram[] = "IOS.Gemini.FRE.EntryPoint";

const char kFirstRunPromoActionHistogram[] = "IOS.Gemini.FRE.PromoAction";

const char kFirstRunConsentActionHistogram[] = "IOS.Gemini.FRE.ConsentAction";

const char kGeminiLiveFREOutcomeHistogram[] = "IOS.Gemini.Live.FREOutcome";

const char kGeminiInvocationPageTypeHistogram[] =
    "IOS.Gemini.InvocationPageType";

const char kGeminiPageAvailabilityHistogram[] = "IOS.Gemini.PageAvailability";

const char kGeminiIneligibilityReasonHistogram[] =
    "IOS.Gemini.IneligibilityReason";

const char kStartupTimeWithFirstRunHistogram[] =
    "IOS.Gemini.StartupTime.FirstRun";

const char kStartupTimeNoFirstRunHistogram[] =
    "IOS.Gemini.StartupTime.NotFirstRun";

const char kGeminiFirstRunStateHistogram[] = "IOS.Gemini.FRE.State";

const char kGeminiSessionCancellationHistogram[] =
    "IOS.Gemini.Session.CancellationReason";

const char kGeminiSessionLengthWithPromptHistogram[] =
    "IOS.Gemini.SessionLength.WithPrompt";

const char kGeminiSessionLengthAbandonedHistogram[] =
    "IOS.Gemini.SessionLength.Abandoned";

const char kGeminiSessionLengthFirstRunWithPromptHistogram[] =
    "IOS.Gemini.SessionLength.FRE.WithPrompt";

const char kGeminiSessionLengthFirstRunAbandonedHistogram[] =
    "IOS.Gemini.SessionLength.FRE.Abandoned";

const char kGeminiSessionTimeHistogram[] = "IOS.Gemini.Session.Time";

const char kFirstPromptSubmissionMethodHistogram[] =
    "IOS.Gemini.FirstPrompt.SubmissionMethod";

const char kPromptSubmissionMethodHistogram[] =
    "IOS.Gemini.Prompt.SubmissionMethod";

const char kPromptImagesAttachedCountHistogram[] =
    "IOS.Gemini.Prompt.ImagesAttached.Count";

const char kPromptImageRemixEnabledHistogram[] =
    "IOS.Gemini.Prompt.ImageRemix.Enabled";

const char kPromptLongPressImageIncludedHistogram[] =
    "IOS.Gemini.Prompt.LongPressImage.Included";

const char kPromptContextAttachmentHistogram[] =
    "IOS.Gemini.Prompt.ContextAttachment";

const char kPromptTabsAttachedCountHistogram[] =
    "IOS.Gemini.Prompt.TabsAttachedCount";

const char kPromptMultiTabUsedHistogram[] = "IOS.Gemini.Prompt.MultiTabUsed";

const char kBlockQuerySubmissionWhileLoadingHistogram[] =
    "IOS.Gemini.BlockQuerySubmissionWhileLoading";

const char kShowPageLoadingSnackbarOnOpeningInvocationHistogram[] =
    "IOS.Gemini.ShowPageLoadingSnackbarOnOpeningInvocation";

const char kResponseGeneratedImageIncluded[] =
    "IOS.Gemini.Response.GeneratedImage.Included";

const char kRegenerateButtonTappedHistogram[] =
    "IOS.Gemini.RegenerateButton.Tapped";

const char kResponseLatencyHistogram[] = "IOS.Gemini.Response.Latency";

const char kResponseLatencyMultiTabUsedHistogram[] =
    "IOS.Gemini.Response.Latency.MultiTabUsed";

const char kResponseLatencyMultiTabNotUsedHistogram[] =
    "IOS.Gemini.Response.Latency.MultiTabNotUsed";

const char kResponseLatencyWithContextHistogram[] =
    "IOS.Gemini.Response.Latency.WithContext";

const char kResponseLatencyWithoutContextHistogram[] =
    "IOS.Gemini.Response.Latency.WithoutContext";

const char kResponseLatencyWithGeneratedImageHistogram[] =
    "IOS.Gemini.Response.Latency.WithGeneratedImage";

const char kResponseLatencyWithoutGeneratedImageHistogram[] =
    "IOS.Gemini.Response.Latency.WithoutGeneratedImage";

const char kSessionPromptCountHistogram[] = "IOS.Gemini.Session.PromptCount";

const char kSessionFirstPromptHistogram[] = "IOS.Gemini.Session.FirstPrompt";

const char kSessionTabSwitchCountHistogram[] =
    "IOS.Gemini.Session.TabSwitchCount";

const char kGeminiLiveDormantReasonHistogram[] =
    "IOS.Gemini.Live.DormantReason";
const char kGeminiLiveResponseLatencyHistogram[] =
    "IOS.Gemini.Live.ResponseLatency";
const char kGeminiLiveResponseDurationHistogram[] =
    "IOS.Gemini.Live.ResponseDuration";
const char kGeminiLiveTurnCountHistogram[] = "IOS.Gemini.Live.TurnCount";
const char kGeminiLiveAccumulatedDurationHistogram[] =
    "IOS.Gemini.Live.AccumulatedDuration";

const char kFloatyTimeMinimizedHistogram[] = "IOS.Gemini.Floaty.TimeMinimized";

const char kFloatyViewStateTransitionHistogram[] =
    "IOS.Gemini.Floaty.ViewStateTransition";

const char kFloatyShownFromSourceHistogram[] =
    "IOS.Gemini.Floaty.ShownFromSource";

const char kFloatyHiddenFromSourceHistogram[] =
    "IOS.Gemini.Floaty.HiddenFromSource";

const char kFloatyDismissedStateHistogram[] =
    "IOS.Gemini.Floaty.DismissedState";

const char kImageRemixContextMenuEntryPointAspectRatioTappedHistogram[] =
    "IOS.Gemini.ImageRemix.ContextMenuEntryPoint.AspectRatio.Tapped";

const char kCameraFlowOSCameraAuthorizationInitialStatusHistogram[] =
    "IOS.Gemini.CameraFlow.OSCameraAuthorization.InitialStatus";

const char kCameraFlowOSAuthorizationRequestResultHistogram[] =
    "IOS.Gemini.CameraFlow.OSCameraAuthorizationRequest.Result";

const char kCameraFlowGoToOSSettingsAlertResultHistogram[] =
    "IOS.Gemini.CameraFlow.GoToOSSettingsAlert.Result";

const char kCameraFlowGeminiCameraPermissionInitialValueHistogram[] =
    "IOS.Gemini.CameraFlow.GeminiCameraPermission.InitialValue";

const char kCameraFlowGeminiCameraPermissionAlertResultHistogram[] =
    "IOS.Gemini.CameraFlow.GeminiCameraPermissionAlert.Result";

const char kCameraFlowCameraPickerResultHistogram[] =
    "IOS.Gemini.CameraFlow.CameraPicker.Result";

const char kEditMenuSelectedTextLengthHistogram[] =
    "IOS.Gemini.EditMenuPrompt.SelectedText.Length";

const char kGlicContextualCueDecisionHistogram[] =
    "IOS.Gemini.GlicContextualCue.Decision";

void RecordFirstRunPromoAction(IOSGeminiFirstRunAction action) {
  switch (action) {
    case IOSGeminiFirstRunAction::kAccept:
      RecordFirstRunPromoAccept();
      break;
    case IOSGeminiFirstRunAction::kDismiss:
      RecordFirstRunPromoDismiss();
      break;
    default:
      break;
  }
  base::UmaHistogramEnumeration(kFirstRunPromoActionHistogram, action);
}

void RecordFirstRunConsentAction(IOSGeminiFirstRunAction action) {
  switch (action) {
    case IOSGeminiFirstRunAction::kAccept:
      RecordFirstRunConsentAccept();
      break;
    case IOSGeminiFirstRunAction::kDismiss:
      RecordFirstRunConsentDismiss();
      break;
    case IOSGeminiFirstRunAction::kLinkClick:
      RecordFirstRunConsentLinkClick();
      break;
    default:
      break;
  }
  base::UmaHistogramEnumeration(kFirstRunConsentActionHistogram, action);
}

void RecordLiveFREOutcome(IOSGeminiLiveFREOutcome outcome) {
  base::UmaHistogramEnumeration(kGeminiLiveFREOutcomeHistogram, outcome);
}

void RecordLiveButtonTapped() {
  base::RecordAction(base::UserMetricsAction("MobileGeminiLiveButtonTapped"));
}

void RecordLiveSessionStarted() {
  base::RecordAction(base::UserMetricsAction("MobileGeminiLiveSessionStarted"));
}

void RecordLiveOSMicPromptShown() {
  base::RecordAction(
      base::UserMetricsAction("MobileGeminiLiveOSMicPromptShown"));
}

void RecordLiveOSMicPromptAllowed() {
  base::RecordAction(
      base::UserMetricsAction("MobileGeminiLiveOSMicPromptAllowed"));
}

void RecordLiveOSMicPromptDenied() {
  base::RecordAction(
      base::UserMetricsAction("MobileGeminiLiveOSMicPromptDenied"));
}

void RecordLiveChromeMicPromptShown() {
  base::RecordAction(
      base::UserMetricsAction("MobileGeminiLiveChromeMicPromptShown"));
}

void RecordLiveChromeMicPromptAllowed() {
  base::RecordAction(
      base::UserMetricsAction("MobileGeminiLiveChromeMicPromptAllowed"));
}

void RecordLiveChromeMicPromptDenied() {
  base::RecordAction(
      base::UserMetricsAction("MobileGeminiLiveChromeMicPromptDenied"));
}

void RecordLiveSettingsRedirectShown() {
  base::RecordAction(
      base::UserMetricsAction("MobileGeminiLiveSettingsRedirectShown"));
}

void RecordLiveSettingsRedirectOpenSettings() {
  base::RecordAction(
      base::UserMetricsAction("MobileGeminiLiveSettingsRedirectOpenSettings"));
}

void RecordLiveSettingsRedirectCancel() {
  base::RecordAction(
      base::UserMetricsAction("MobileGeminiLiveSettingsRedirectCancel"));
}

void RecordGeminiInvocationPageType(IOSGeminiInvocationPageType page_type) {
  base::UmaHistogramEnumeration(kGeminiInvocationPageTypeHistogram, page_type);
}

void RecordGeminiPageAvailability(IOSGeminiPageAvailability reason) {
  base::UmaHistogramEnumeration(kGeminiPageAvailabilityHistogram, reason);
}

void RecordGeminiEligibility(bool eligible) {
  base::UmaHistogramBoolean(kEligibilityHistogram, eligible);
}

void RecordGeminiFirstRunState(gemini::FirstRunState state) {
  base::UmaHistogramEnumeration(kGeminiFirstRunStateHistogram, state);
}

void RecordGeminiIneligibilityReasons(gemini::IneligibilityReasons reasons) {
  if (reasons.workspace) {
    base::UmaHistogramEnumeration(
        kGeminiIneligibilityReasonHistogram,
        IOSGeminiIneligibilityReason::kWorkspaceRestricted);
  }
  if (reasons.chrome_enterprise) {
    base::UmaHistogramEnumeration(
        kGeminiIneligibilityReasonHistogram,
        IOSGeminiIneligibilityReason::kChromeEnterpriseDisabled);
  }
  if (reasons.account_capability) {
    base::UmaHistogramEnumeration(
        kGeminiIneligibilityReasonHistogram,
        IOSGeminiIneligibilityReason::kInsufficientAccountCapability);
  }
  if (reasons.authentication) {
    base::UmaHistogramEnumeration(
        kGeminiIneligibilityReasonHistogram,
        IOSGeminiIneligibilityReason::kAccountUnauthenticated);
  }
}

void RecordGeminiSessionCancellation(
    IOSGeminiSessionCancellationReason reason) {
  base::UmaHistogramEnumeration(kGeminiSessionCancellationHistogram, reason);
}

void RecordGeminiSessionOpened() {
  base::RecordAction(base::UserMetricsAction("MobileGeminiSessionOpened"));
}

void RecordGeminiSessionTime(base::TimeDelta session_duration) {
  base::UmaHistogramLongTimes100(kGeminiSessionTimeHistogram, session_duration);
}

void RecordGeminiSessionLengthByType(base::TimeDelta session_duration,
                                     bool is_first_run,
                                     IOSGeminiSessionType session_type) {
  if (is_first_run) {
    switch (session_type) {
      case IOSGeminiSessionType::kWithPrompt:
        base::UmaHistogramLongTimes100(
            kGeminiSessionLengthFirstRunWithPromptHistogram, session_duration);
        break;
      case IOSGeminiSessionType::kAbandoned:
        base::UmaHistogramLongTimes100(
            kGeminiSessionLengthFirstRunAbandonedHistogram, session_duration);
        break;
      case IOSGeminiSessionType::kUnknown:
        break;
    }
  } else {
    switch (session_type) {
      case IOSGeminiSessionType::kWithPrompt:
        base::UmaHistogramLongTimes100(kGeminiSessionLengthWithPromptHistogram,
                                       session_duration);
        break;
      case IOSGeminiSessionType::kAbandoned:
        base::UmaHistogramLongTimes100(kGeminiSessionLengthAbandonedHistogram,
                                       session_duration);
        break;
      case IOSGeminiSessionType::kUnknown:
        break;
    }
  }
}

void RecordGeminiEntryPointImpression(gemini::EntryPoint entry_point) {
  base::TimeTicks now = base::TimeTicks::Now();
  base::TimeTicks& last_impression_time = GetLastGeminiImpressionTime();

  // Check if enough time has passed since last impression.
  if (last_impression_time.is_null() ||
      (now - last_impression_time) >= kGeminiImpressionThrottleInterval) {
    base::RecordAction(
        base::UserMetricsAction("MobileGeminiEntryPointImpression"));
    base::UmaHistogramEnumeration(kEntryPointImpressionHistogram, entry_point);
    last_impression_time = now;
  }
}

void RecordGeminiEntryPointAvailable(gemini::EntryPoint entry_point) {
  base::RecordAction(
      base::UserMetricsAction("MobileGeminiEntryPointAvailable"));
  base::UmaHistogramEnumeration(kEntryPointAvailableHistogram, entry_point);
}

void RecordFirstRunShown() {
  base::RecordAction(base::UserMetricsAction("MobileGeminiFREShown"));
}

void RecordFirstResponseReceived() {
  base::RecordAction(
      base::UserMetricsAction("MobileGeminiFirstResponseReceived"));
}

void RecordFirstPromptSubmission(IOSGeminiFirstPromptSubmissionMethod method) {
  base::RecordAction(
      base::UserMetricsAction("MobileGeminiFirstPromptSubmitted"));
  base::UmaHistogramEnumeration(kFirstPromptSubmissionMethodHistogram, method);
}

void RecordPromptSubmissionMethod(IOSGeminiFirstPromptSubmissionMethod method) {
  base::UmaHistogramEnumeration(kPromptSubmissionMethodHistogram, method);
}

void RecordGeminiResponseReceived(bool generated_image_included) {
  base::RecordAction(base::UserMetricsAction("MobileGeminiResponseReceived"));
  base::UmaHistogramBoolean(kResponseGeneratedImageIncluded,
                            generated_image_included);
}

void RecordFirstRunPromoAccept() {
  base::RecordAction(base::UserMetricsAction("MobileGeminiFREPromoAccept"));
}

void RecordFirstRunPromoDismiss() {
  base::RecordAction(base::UserMetricsAction("MobileGeminiFREPromoCancel"));
}

void RecordFirstRunConsentAccept() {
  base::RecordAction(base::UserMetricsAction("MobileGeminiFREConsentAccept"));
}

void RecordFirstRunConsentDismiss() {
  base::RecordAction(base::UserMetricsAction("MobileGeminiFREConsentDismiss"));
}

void RecordFirstRunConsentLinkClick() {
  base::RecordAction(
      base::UserMetricsAction("MobileGeminiFREConsentLinkClick"));
}

void RecordGeminiTabPickerOpened() {
  base::RecordAction(base::UserMetricsAction("MobileGeminiTabPickerOpened"));
}

void RecordGeminiTabPickerDismissed() {
  base::RecordAction(base::UserMetricsAction("MobileGeminiTabPickerDismissed"));
}

void RecordGeminiTabPickerErrorAttachmentLimit() {
  base::RecordAction(
      base::UserMetricsAction("MobileGeminiTabPickerErrorAttachmentLimit"));
}

void RecordGeminiTabPickerErrorCannotReloadTab() {
  base::RecordAction(
      base::UserMetricsAction("MobileGeminiTabPickerErrorCannotReloadTab"));
}

void RecordGeminiTabPickerErrorCannotAttachTab() {
  base::RecordAction(
      base::UserMetricsAction("MobileGeminiTabPickerErrorCannotAttachTab"));
}

void RecordGeminiTabDetached() {
  base::RecordAction(base::UserMetricsAction("MobileGeminiTabDetached"));
}

void RecordGeminiActiveTabAttached() {
  base::RecordAction(base::UserMetricsAction("MobileGeminiActiveTabAttached"));
}

void RecordGeminiActiveTabDetached() {
  base::RecordAction(base::UserMetricsAction("MobileGeminiActiveTabDetached"));
}

void RecordResponseLatency(base::TimeDelta latency,
                           bool had_page_context,
                           bool had_generated_image,
                           bool was_multi_tab_used) {
  base::UmaHistogramMediumTimes(kResponseLatencyHistogram, latency);

  if (was_multi_tab_used) {
    base::UmaHistogramMediumTimes(kResponseLatencyMultiTabUsedHistogram,
                                  latency);
  } else {
    base::UmaHistogramMediumTimes(kResponseLatencyMultiTabNotUsedHistogram,
                                  latency);
  }

  if (had_page_context) {
    base::UmaHistogramMediumTimes(kResponseLatencyWithContextHistogram,
                                  latency);
  } else {
    base::UmaHistogramMediumTimes(kResponseLatencyWithoutContextHistogram,
                                  latency);
  }

  if (had_generated_image) {
    base::UmaHistogramMediumTimes(kResponseLatencyWithGeneratedImageHistogram,
                                  latency);
  } else {
    base::UmaHistogramMediumTimes(
        kResponseLatencyWithoutGeneratedImageHistogram, latency);
  }
}

void RecordSessionPromptCount(int prompt_count) {
  base::UmaHistogramCounts100(kSessionPromptCountHistogram, prompt_count);
}

void RecordSessionFirstPrompt(bool had_first_prompt) {
  base::UmaHistogramBoolean(kSessionFirstPromptHistogram, had_first_prompt);
}

void RecordSessionTabSwitchCount(int tab_switch_count) {
  base::UmaHistogramCounts100(kSessionTabSwitchCountHistogram,
                              tab_switch_count);
}

void RecordFloatyExpandedToCollapsed() {
  base::RecordAction(
      base::UserMetricsAction("MobileGeminiFloatyExpandedToCollapsed"));
  RecordGeminiViewStateTransition(
      IOSGeminiViewStateTransition::kExpandedToCollapsed);
}

void RecordFloatyCollapsedToExpanded() {
  base::RecordAction(
      base::UserMetricsAction("MobileGeminiFloatyCollapsedToExpanded"));
  RecordGeminiViewStateTransition(
      IOSGeminiViewStateTransition::kCollapsedToExpanded);
}

void RecordFloatyDismissedState(ios::provider::GeminiViewState state) {
  base::UmaHistogramEnumeration(kFloatyDismissedStateHistogram, state);

  if (state == ios::provider::GeminiViewState::kCollapsed) {
    base::RecordAction(
        base::UserMetricsAction("MobileGeminiFloatyCollapsedToDismissed"));
  } else if (state == ios::provider::GeminiViewState::kExpanded) {
    base::RecordAction(
        base::UserMetricsAction("MobileGeminiFloatyExpandedToDismissed"));
  }
}

void RecordFloatyMinimizedTime(base::TimeTicks elapsed_minimized_floaty_time) {
  if (elapsed_minimized_floaty_time.is_null()) {
    return;
  }

  base::TimeDelta minimized_floaty_time =
      base::TimeTicks::Now() - elapsed_minimized_floaty_time;
  base::UmaHistogramLongTimes100(kFloatyTimeMinimizedHistogram,
                                 minimized_floaty_time);
}

void RecordGeminiViewStateTransition(IOSGeminiViewStateTransition transition) {
  base::UmaHistogramEnumeration(kFloatyViewStateTransitionHistogram,
                                transition);
}

void RecordGeminiViewStateHiddenToShown(
    ios::provider::GeminiViewState view_state) {
  switch (view_state) {
    case ios::provider::GeminiViewState::kCollapsed:
      RecordGeminiViewStateTransition(
          IOSGeminiViewStateTransition::kHiddenToCollapsed);
      break;
    case ios::provider::GeminiViewState::kExpanded:
      RecordGeminiViewStateTransition(
          IOSGeminiViewStateTransition::kHiddenToExpanded);
      break;
    default:
      break;
  }
}

void RecordFloatyShownFromSource(gemini::FloatyUpdateSource source) {
  base::UmaHistogramEnumeration(kFloatyShownFromSourceHistogram, source);
}

void RecordFloatyHiddenFromSource(gemini::FloatyUpdateSource source) {
  base::UmaHistogramEnumeration(kFloatyHiddenFromSourceHistogram, source);
}

void RecordURLOpened() {
  base::RecordAction(base::UserMetricsAction("MobileGeminiURLOpened"));
}

void RecordGeminiEntryPointClick(gemini::EntryPoint entry_point,
                                 bool is_fre_flow) {
  if (entry_point == gemini::EntryPoint::Promo) {
    base::RecordAction(
        base::UserMetricsAction("MobileGeminiEntryPointAutomatic"));
  } else {
    base::RecordAction(base::UserMetricsAction("MobileGeminiEntryPointTapped"));
  }
  base::UmaHistogramEnumeration(kEntryPointHistogram, entry_point);
  if (is_fre_flow) {
    base::UmaHistogramEnumeration(kFirstRunEntryPointHistogram, entry_point);
  }
}

void RecordSignInRequiredSnackbarShown(gemini::EntryPoint entry_point) {
  base::UmaHistogramEnumeration(kSignInRequiredSnackbarShownHistogram,
                                entry_point);
}

void RecordGeminiNewChatButtonTapped() {
  base::RecordAction(base::UserMetricsAction("MobileGeminiNewChatTapped"));
}

void RecordGeminiRegenerateButtonTapped(gemini::RegenerateOptionType option) {
  base::RecordAction(
      base::UserMetricsAction("MobileGeminiRegenerateButtonTapped"));
  base::UmaHistogramEnumeration(kRegenerateButtonTappedHistogram, option);
}

void RecordAIHubNewBadgeTapped() {
  base::RecordAction(base::UserMetricsAction("MobileAIHubNewBadgeTapped"));
}

void RecordAIHubIconTapped() {
  base::RecordAction(base::UserMetricsAction("MobileAIHubIconTapped"));
}

void RecordGeminiPromptSent(bool is_nano_banana_enabled,
                            int images_attached_count,
                            bool long_press_image_included,
                            bool has_page_context,
                            int tabs_attached_count,
                            bool was_multi_tab_used) {
  base::RecordAction(base::UserMetricsAction("MobileGeminiPromptSent"));
  base::UmaHistogramBoolean(kPromptImageRemixEnabledHistogram,
                            is_nano_banana_enabled);
  base::UmaHistogramCounts100(kPromptImagesAttachedCountHistogram,
                              images_attached_count);
  base::UmaHistogramBoolean(kPromptLongPressImageIncludedHistogram,
                            long_press_image_included);
  base::UmaHistogramBoolean(kPromptContextAttachmentHistogram,
                            has_page_context);
  base::UmaHistogramCounts100(kPromptTabsAttachedCountHistogram,
                              tabs_attached_count);
  base::UmaHistogramBoolean(kPromptMultiTabUsedHistogram, was_multi_tab_used);
}

void RecordGeminiFeedback(IOSGeminiFeedback feedback) {
  base::UmaHistogramEnumeration(kFeedbackHistogram, feedback);

  switch (feedback) {
    case IOSGeminiFeedback::kThumbsUp:
      base::RecordAction(
          base::UserMetricsAction("MobileGeminiFeedbackThumbsUp"));
      break;
    case IOSGeminiFeedback::kThumbsDown:
      base::RecordAction(
          base::UserMetricsAction("MobileGeminiFeedbackThumbsDown"));
      break;
  }
}

void RecordImageRemixContextMenuEntryPointShown() {
  base::RecordAction(base::UserMetricsAction(
      "MobileGeminiImageRemixContextMenuEntryPointShown"));
}

void RecordImageRemixContextMenuEntryPointTapped(double aspect_ratio) {
  base::RecordAction(base::UserMetricsAction(
      "MobileGeminiImageRemixContextMenuEntryPointTapped"));
  base::UmaHistogramEnumeration(
      kImageRemixContextMenuEntryPointAspectRatioTappedHistogram,
      GetAspectRatioBucket(aspect_ratio));
}

void RecordGeminiCameraFlowBegan() {
  base::RecordAction(base::UserMetricsAction("MobileGeminiCameraFlowBegan"));
}

void RecordGeminiCameraFlowOSCameraAuthorizationInitialStatus(
    IOSGeminiOSCameraAuthorizationInitialStatus authorization_status) {
  base::UmaHistogramEnumeration(
      kCameraFlowOSCameraAuthorizationInitialStatusHistogram,
      authorization_status);
}

void RecordGeminiCameraFlowOSAuthorizationResult(bool granted) {
  if (granted) {
    base::RecordAction(base::UserMetricsAction(
        "MobileGeminiCameraFlowOSCameraAuthorizationRequestGranted"));
  } else {
    base::RecordAction(base::UserMetricsAction(
        "MobileGeminiCameraFlowOSCameraAuthorizationRequestDenied"));
  }
  base::UmaHistogramEnumeration(
      kCameraFlowOSAuthorizationRequestResultHistogram,
      granted ? IOSGeminiCameraFlowOSCameraAuthorizationResult::kGranted
              : IOSGeminiCameraFlowOSCameraAuthorizationResult::kDenied);
}

void RecordGeminiCameraFlowGoToOSSettingsAlertResult(bool accepted) {
  if (accepted) {
    base::RecordAction(base::UserMetricsAction(
        "MobileGeminiCameraFlowGoToOSSettingsAlertGoToSettings"));
  } else {
    base::RecordAction(base::UserMetricsAction(
        "MobileGeminiCameraFlowGoToOSSettingsAlertNoThanks"));
  }
  base::UmaHistogramEnumeration(
      kCameraFlowGoToOSSettingsAlertResultHistogram,
      accepted ? IOSGeminiGoToOSSettingsAlertResult::kGoToSettings
               : IOSGeminiGoToOSSettingsAlertResult::kNoThanks);
}

void RecordGeminiCameraFlowGeminiCameraPermissionInitialValue(bool enabled) {
  base::UmaHistogramBoolean(
      kCameraFlowGeminiCameraPermissionInitialValueHistogram, enabled);
}

void RecordGeminiCameraFlowGeminiCameraPermissionAlertResult(bool allowed) {
  if (allowed) {
    base::RecordAction(base::UserMetricsAction(
        "MobileGeminiCameraFlowGeminiCameraPermissionAlertAllow"));
  } else {
    base::RecordAction(base::UserMetricsAction(
        "MobileGeminiCameraFlowGeminiCameraPermissionAlertDontAllow"));
  }
  base::UmaHistogramEnumeration(
      kCameraFlowGeminiCameraPermissionAlertResultHistogram,
      allowed ? IOSGeminiCameraPermissionAlertResult::kAllow
              : IOSGeminiCameraPermissionAlertResult::kDontAllow);
}

void RecordGeminiCameraFlowPresentCameraPicker() {
  base::RecordAction(
      base::UserMetricsAction("MobileGeminiCameraFlowCameraPickerPresented"));
}

void RecordGeminiCameraFlowCameraPickerResult(
    IOSGeminiCameraPickerResult result) {
  switch (result) {
    case IOSGeminiCameraPickerResult::kCancelled:
      base::RecordAction(base::UserMetricsAction(
          "MobileGeminiCameraFlowCameraPickerCancelled"));
      break;
    case IOSGeminiCameraPickerResult::kFinishedWithoutImage:
      base::RecordAction(base::UserMetricsAction(
          "MobileGeminiCameraFlowCameraPickerFinishedWithoutImage"));
      break;
    case IOSGeminiCameraPickerResult::kFinishedWithImage:
      base::RecordAction(base::UserMetricsAction(
          "MobileGeminiCameraFlowCameraPickerFinishedWithImage"));
      break;
  }
  base::UmaHistogramEnumeration(kCameraFlowCameraPickerResultHistogram, result);
}

void RecordGeminiImageActionButtonTapped(gemini::ImageActionButtonType type) {
  base::RecordAction(
      base::UserMetricsAction("MobileGeminiImageActionButtonTapped"));
  base::UmaHistogramEnumeration(kImageActionButtonHistogram, type);
}

void RecordGeminiInputPlateAttachmentOptionTapped(
    gemini::InputPlateAttachmentOption option) {
  base::RecordAction(
      base::UserMetricsAction("MobileGeminiInputPlateAttachmentOptionTapped"));
  base::UmaHistogramEnumeration(kInputPlateAttachmentOptionHistogram, option);
}

void RecordGeminiEditMenuSelectedTextLength(int length) {
  base::UmaHistogramCounts1000(kEditMenuSelectedTextLengthHistogram, length);
}

void RecordGeminiGlicContextualCueDecision(
    optimization_guide::OptimizationGuideDecision decision) {
  base::UmaHistogramEnumeration(kGlicContextualCueDecisionHistogram, decision);
}

void RecordGeminiLiveDormantReason(ios::provider::GeminiDormantReason reason) {
  IOSGeminiDormantReason uma_reason = IOSGeminiDormantReason::kUnknown;
  switch (reason) {
    case ios::provider::GeminiDormantReason::kUnknown:
      uma_reason = IOSGeminiDormantReason::kUnknown;
      break;
    case ios::provider::GeminiDormantReason::kInterruptedByExternalAudio:
      uma_reason = IOSGeminiDormantReason::kInterruptedByExternalAudio;
      break;
    case ios::provider::GeminiDormantReason::kLowVolumeInBackground:
      uma_reason = IOSGeminiDormantReason::kLowVolumeInBackground;
      break;
    case ios::provider::GeminiDormantReason::kLowVolumeInForeground:
      uma_reason = IOSGeminiDormantReason::kLowVolumeInForeground;
      break;
    case ios::provider::GeminiDormantReason::kInactivityTimeout:
      uma_reason = IOSGeminiDormantReason::kInactivityTimeout;
      break;
    case ios::provider::GeminiDormantReason::kLongInteractionTimeout:
      uma_reason = IOSGeminiDormantReason::kLongInteractionTimeout;
      break;
    case ios::provider::GeminiDormantReason::kMovedToBackgroundWhenMicOff:
      uma_reason = IOSGeminiDormantReason::kMovedToBackgroundWhenMicOff;
      break;
    case ios::provider::GeminiDormantReason::kUserStop:
      uma_reason = IOSGeminiDormantReason::kUserStop;
      break;
    case ios::provider::GeminiDormantReason::kUserPause:
      uma_reason = IOSGeminiDormantReason::kUserPause;
      break;
    case ios::provider::GeminiDormantReason::kServerPause:
      uma_reason = IOSGeminiDormantReason::kServerPause;
      break;
  }
  base::UmaHistogramEnumeration(kGeminiLiveDormantReasonHistogram, uma_reason);
}

void RecordGeminiLiveResponseLatency(base::TimeDelta latency) {
  base::UmaHistogramTimes(kGeminiLiveResponseLatencyHistogram, latency);
}

void RecordGeminiLiveResponseDuration(base::TimeDelta duration) {
  base::UmaHistogramMediumTimes(kGeminiLiveResponseDurationHistogram, duration);
}

void RecordGeminiLiveTurnCount(int turn_count) {
  base::UmaHistogramCounts100(kGeminiLiveTurnCountHistogram, turn_count);
}

void RecordGeminiLiveAccumulatedDuration(base::TimeDelta duration) {
  base::UmaHistogramLongTimes(kGeminiLiveAccumulatedDurationHistogram,
                              duration);
}

void RecordBlockQuerySubmissionWhileLoading(bool block_submission) {
  base::UmaHistogramBoolean(kBlockQuerySubmissionWhileLoadingHistogram,
                            block_submission);
}

void RecordShowPageLoadingSnackbarOnOpeningInvocation(bool show_snackbar) {
  base::UmaHistogramBoolean(
      kShowPageLoadingSnackbarOnOpeningInvocationHistogram, show_snackbar);
}
