// Copyright 2023 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/compose/compose_session.h"

#include <cmath>
#include <memory>
#include <string>
#include <string_view>
#include <utility>

#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/location.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/user_metrics.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/thread_pool.h"
#include "base/time/time.h"
#include "base/timer/elapsed_timer.h"
#include "base/timer/timer.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/feedback/show_feedback_page.h"
#include "chrome/browser/optimization_guide/optimization_guide_keyed_service.h"
#include "chrome/browser/optimization_guide/optimization_guide_keyed_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_dialogs.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/chrome_pages.h"
#include "chrome/browser/ui/hats/hats_service_factory.h"
#include "chrome/browser/ui/hats/survey_config.h"
#include "chrome/common/compose/type_conversions.h"
#include "chrome/common/webui_url_constants.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/compose/core/browser/compose_features.h"
#include "components/compose/core/browser/compose_hats_utils.h"
#include "components/compose/core/browser/compose_manager_impl.h"
#include "components/compose/core/browser/compose_metrics.h"
#include "components/compose/core/browser/compose_utils.h"
#include "components/compose/core/browser/config.h"
#include "components/content_extraction/content/browser/inner_text.h"
#include "components/optimization_guide/core/model_execution/feature_keys.h"
#include "components/optimization_guide/core/model_execution/optimization_guide_model_execution_error.h"
#include "components/optimization_guide/core/model_quality/model_execution_logging_wrappers.h"
#include "components/optimization_guide/core/model_quality/model_quality_log_entry.h"
#include "components/optimization_guide/core/optimization_guide_features.h"
#include "components/optimization_guide/core/optimization_guide_model_executor.h"
#include "components/optimization_guide/core/optimization_guide_proto_util.h"
#include "components/optimization_guide/core/optimization_guide_util.h"
#include "components/optimization_guide/proto/features/compose.pb.h"
#include "components/optimization_guide/proto/model_quality_service.pb.h"
#include "components/strings/grit/components_strings.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/browser/page_navigator.h"
#include "content/public/browser/web_contents_user_data.h"
#include "content/public/common/referrer.h"
#include "mojo/public/cpp/bindings/callback_helpers.h"
#include "ui/accessibility/ax_mode.h"
#include "ui/accessibility/ax_tree_update.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/page_transition_types.h"
#include "ui/base/window_open_disposition.h"
#include "ui/gfx/geometry/rect_f.h"

namespace {

bool IsValidComposePrompt(const std::string& prompt) {
  const compose::Config& config = compose::GetComposeConfig();
  if (prompt.length() > config.input_max_chars) {
    return false;
  }

  return compose::IsWordCountWithinBounds(prompt, config.input_min_words,
                                          config.input_max_words);
}

const char kComposeBugReportURL[] = "https://goto.google.com/ccbrfd";
const char kOnDeviceComposeBugReportURL[] = "https://goto.google.com/ccbrfdod";
const char kComposeLearnMorePageURL[] =
    "https://support.google.com/chrome?p=help_me_write";
// TODO(crbug.com/40500621): Replace with p-link
const char kEnterpriseComposeLearnMorePageURL[] =
    "https://support.google.com/chrome/a/answer/14443058";
const char kComposeFeedbackSurveyURL[] = "https://goto.google.com/ccfsfd";
const char kSignInPageURL[] = "https://accounts.google.com";
const char kOnDeviceComposeFeedbackSurveyURL[] =
    "https://goto.google.com/ccfsfdod";

compose::EvalLocation GetEvalLocation(
    const optimization_guide::OptimizationGuideModelStreamingExecutionResult&
        result) {
  return result.provided_by_on_device ? compose::EvalLocation::kOnDevice
                                      : compose::EvalLocation::kServer;
}

compose::ComposeRequestReason GetRequestReasonForInputMode(
    compose::mojom::InputMode mode) {
  switch (mode) {
    case compose::mojom::InputMode::kElaborate:
      return compose::ComposeRequestReason::kFirstRequestElaborateMode;
    case compose::mojom::InputMode::kFormalize:
      return compose::ComposeRequestReason::kFirstRequestFormalizeMode;
    case compose::mojom::InputMode::kPolish:
      return compose::ComposeRequestReason::kFirstRequestPolishMode;
    case compose::mojom::InputMode::kUnset:
      return compose::ComposeRequestReason::kFirstRequest;
  }
}

bool WasRequestTriggeredFromModifier(compose::ComposeRequestReason reason) {
  switch (reason) {
    case compose::ComposeRequestReason::kRetryRequest:
    case compose::ComposeRequestReason::kLengthShortenRequest:
    case compose::ComposeRequestReason::kLengthElaborateRequest:
    case compose::ComposeRequestReason::kToneCasualRequest:
    case compose::ComposeRequestReason::kToneFormalRequest:
      return true;
    case compose::ComposeRequestReason::kUpdateRequest:
    case compose::ComposeRequestReason::kFirstRequest:
    case compose::ComposeRequestReason::kFirstRequestPolishMode:
    case compose::ComposeRequestReason::kFirstRequestElaborateMode:
    case compose::ComposeRequestReason::kFirstRequestFormalizeMode:
      return false;
  }
}

}  // namespace

// The state of a compose session. This currently includes the model quality log
// entry, and the mojo based compose state.
class ComposeState {
 public:
  ComposeState() {
    modeling_log_entry_ = nullptr;
    mojo_state_ = nullptr;
  }

  ComposeState(std::unique_ptr<optimization_guide::ModelQualityLogEntry>
                   modeling_log_entry,
               compose::mojom::ComposeStatePtr mojo_state) {
    modeling_log_entry_ = std::move(modeling_log_entry);
    mojo_state_ = std::move(mojo_state);
  }

  ~ComposeState() = default;

  bool IsMojoValid() {
    return (mojo_state_ && mojo_state_->response &&
            mojo_state_->response->status ==
                compose::mojom::ComposeStatus::kOk &&
            mojo_state_->response->result != "");
  }

  optimization_guide::ModelQualityLogEntry* modeling_log_entry() {
    return modeling_log_entry_.get();
  }
  std::unique_ptr<optimization_guide::ModelQualityLogEntry>
  TakeModelingLogEntry() {
    auto to_return = std::move(modeling_log_entry_);
    return to_return;
  }

  void SetModelingLogEntry(
      std::unique_ptr<optimization_guide::ModelQualityLogEntry>
          modeling_log_entry) {
    modeling_log_entry_ = std::move(modeling_log_entry);
  }

  compose::mojom::ComposeState* mojo_state() { return mojo_state_.get(); }
  compose::mojom::ComposeStatePtr TakeMojoState() {
    auto to_return = std::move(mojo_state_);
    return to_return;
  }

  bool is_user_edited() { return is_user_edited_; }
  std::string original_response() { return original_response_; }

  void SetUserEdited(std::string original_response) {
    original_response_ = original_response;
    is_user_edited_ = true;
  }

  void UnsetUserEdited() {
    original_response_ = "";
    is_user_edited_ = false;
  }

  void SetMojoState(compose::mojom::ComposeStatePtr mojo_state) {
    mojo_state_ = std::move(mojo_state);
  }

  void UploadModelQualityLogs() {
    if (!modeling_log_entry_) {
      return;
    }
    LogRequestFeedback();
    optimization_guide::ModelQualityLogEntry::Upload(TakeModelingLogEntry());
  }

  void LogRequestFeedback() {
    if (!mojo_state_ || !mojo_state_->response) {
      // No request or modeling information so nothing to report.
      return;
    }
    if (mojo_state_->response->status != compose::mojom::ComposeStatus::kOk) {
      // Request Feedback was already reported when error was received.
      return;
    }

    compose::EvalLocation eval_location =
        mojo_state_->response->on_device_evaluation_used
            ? compose::EvalLocation::kOnDevice
            : compose::EvalLocation::kServer;
    compose::ComposeRequestFeedback feedback;
    switch (mojo_state_->feedback) {
      case compose::mojom::UserFeedback::kUserFeedbackPositive:
        feedback = compose::ComposeRequestFeedback::kPositiveFeedback;
        break;
      case compose::mojom::UserFeedback::kUserFeedbackNegative:
        feedback = compose::ComposeRequestFeedback::kNegativeFeedback;
        break;
      case compose::mojom::UserFeedback::kUserFeedbackUnspecified:
        feedback = compose::ComposeRequestFeedback::kNoFeedback;
        break;
    }
    compose::LogComposeRequestFeedback(eval_location, feedback);
  }

 private:
  std::unique_ptr<optimization_guide::ModelQualityLogEntry> modeling_log_entry_;
  compose::mojom::ComposeStatePtr mojo_state_;
  std::string original_response_ = "";
  bool is_user_edited_ = false;
};

ComposeSession::ComposeSession(
    content::WebContents* web_contents,
    optimization_guide::OptimizationGuideModelExecutor* executor,
    optimization_guide::ModelQualityLogsUploaderService* model_quality_uploader,
    base::Token session_id,
    InnerTextProvider* inner_text,
    autofill::FieldGlobalId node_id,
    bool is_page_language_supported,
    Observer* observer,
    ComposeCallback callback)
    : executor_(executor),
      model_quality_uploader_(model_quality_uploader),
      handler_receiver_(this),
      web_contents_(web_contents),
      observer_(observer),
      collect_inner_text_(
          base::FeatureList::IsEnabled(compose::features::kComposeInnerText)),
      collect_ax_snapshot_(
          base::FeatureList::IsEnabled(compose::features::kComposeAXSnapshot)),
      inner_text_caller_(inner_text),
      ukm_source_id_(web_contents->GetPrimaryMainFrame()->GetPageUkmSourceId()),
      node_id_(node_id),
      is_page_language_supported_(is_page_language_supported),
      session_id_(session_id),
      weak_ptr_factory_(this) {
  session_duration_ = std::make_unique<base::ElapsedTimer>();
  callback_ = std::move(callback);
  active_mojo_state_ = compose::mojom::ComposeState::New();
  if (executor_) {
    optimization_guide::SessionConfigParams config_params = {
        .execution_mode = base::FeatureList::IsEnabled(
                              compose::features::kComposeAllowOnDeviceExecution)
                              ? optimization_guide::SessionConfigParams::
                                    ExecutionMode::kDefault
                              : optimization_guide::SessionConfigParams::
                                    ExecutionMode::kServerOnly};
    session_ = executor_->StartSession(
        optimization_guide::ModelBasedCapabilityKey::kCompose, config_params);
  }
}

base::optional_ref<ComposeState> ComposeSession::LastResponseState() {
  if (history_.empty() || history_current_index_ >= history_.size() ||
      !history_[history_current_index_]) {
    return std::nullopt;
  }

  if (history_[history_current_index_]->is_user_edited()) {
    // The state at `history_current_index_` is an edited result, so the last
    // response state directly precedes it in `history_`.
    CHECK_GT(history_current_index_, 0u);
    return *history_[history_current_index_ - 1];
  }

  return *history_[history_current_index_];
}

base::optional_ref<ComposeState> ComposeSession::CurrentState(int offset) {
  if (history_.empty() || history_current_index_ + offset >= history_.size() ||
      !history_[history_current_index_ + offset]) {
    return std::nullopt;
  }

  return *history_[history_current_index_ + offset];
}

ComposeSession::~ComposeSession() {
  std::optional<compose::EvalLocation> eval_location =
      compose::GetEvalLocationFromEvents(session_events_);

  if (observer_) {
    observer_->OnSessionComplete(node_id_, close_reason_, session_events_);
  }

  if (session_events_.fre_view_count > 0 &&
      (!fre_complete_ || session_events_.fre_completed_in_session)) {
    compose::LogComposeFirstRunSessionCloseReason(fre_close_reason_);
    compose::LogComposeFirstRunSessionDialogShownCount(
        fre_close_reason_, session_events_.fre_view_count);
    if (!fre_complete_) {
      compose::LogComposeSessionDuration(session_duration_->Elapsed(), ".FRE");
      compose::LogComposeSessionEventCounts(std::nullopt, session_events_);
      compose::LogComposeSessionCloseReason(
          compose::ComposeSessionCloseReason::kEndedAtFre);
      return;
    }
  }
  if (session_events_.msbb_view_count > 0 &&
      (!current_msbb_state_ || session_events_.msbb_enabled_in_session)) {
    compose::LogComposeMSBBSessionDialogShownCount(
        msbb_close_reason_, session_events_.msbb_view_count);
    compose::LogComposeMSBBSessionCloseReason(msbb_close_reason_);
    if (!current_msbb_state_) {
      compose::LogComposeSessionDuration(session_duration_->Elapsed(), ".MSBB");
      compose::LogComposeSessionEventCounts(std::nullopt, session_events_);
      compose::ComposeSessionCloseReason session_close_reason =
          (session_events_.fre_completed_in_session)
              ? compose::ComposeSessionCloseReason::kAckedFreEndedAtMsbb
              : compose::ComposeSessionCloseReason::kEndedAtMsbb;
      compose::LogComposeSessionCloseReason(session_close_reason);
      return;
    }
  }

  if (session_events_.compose_dialog_open_count < 1) {
    // Do not report any further metrics if the dialog was never opened.
    // This is mostly like because the session was the debug session but
    // could occur if the tab closes while Compose is opening.
    return;
  }

  if (session_events_.inserted_results) {
    compose::LogComposeSessionDuration(session_duration_->Elapsed(),
                                       ".Inserted", eval_location);
  } else {
    compose::LogComposeSessionDuration(session_duration_->Elapsed(), ".Ignored",
                                       eval_location);
  }
  if (close_reason_ == compose::ComposeSessionCloseReason::kAbandoned) {
    base::RecordAction(
        base::UserMetricsAction("Compose.EndedSession.EndedImplicitly"));
    final_model_status_ =
        optimization_guide::proto::FinalModelStatus::FINAL_MODEL_STATUS_FAILURE;
    final_status_ =
        optimization_guide::proto::FinalStatus::STATUS_FINISHED_WITHOUT_INSERT;
  }

  LogComposeSessionCloseMetrics(close_reason_, session_events_);

  LogComposeSessionCloseUkmMetrics(ukm_source_id_, session_events_);

  // Quality log would automatically be uploaded on the destruction of
  // a modeling_log_entry. However in order to more easily test the quality
  // uploads we are calling upload directly here.

  if (most_recent_error_log_) {
    // First set final status on most_recent_error_log.
    most_recent_error_log_
        ->log_ai_data_request()
        ->mutable_compose()
        ->mutable_quality()
        ->set_final_status(final_status_);
    most_recent_error_log_
        ->log_ai_data_request()
        ->mutable_compose()
        ->mutable_quality()
        ->set_final_model_status(final_model_status_);

    optimization_guide::ModelQualityLogEntry::Upload(
        std::move(most_recent_error_log_));
  } else if (auto last_response_state = LastResponseState();
             last_response_state.has_value()) {
    if (auto* log_entry = last_response_state->modeling_log_entry()) {
      log_entry->log_ai_data_request()
          ->mutable_compose()
          ->mutable_quality()
          ->set_final_status(final_status_);
      log_entry->log_ai_data_request()
          ->mutable_compose()
          ->mutable_quality()
          ->set_final_model_status(final_model_status_);
      last_response_state->UploadModelQualityLogs();
    }
  }

  for (auto& state : history_) {
    // Upload all saved states with a valid quality logs member (those tied to
    // a ComposeResponse) and then clear all states.
    state->UploadModelQualityLogs();
  }
}

void ComposeSession::Bind(
    mojo::PendingReceiver<compose::mojom::ComposeSessionUntrustedPageHandler>
        handler,
    mojo::PendingRemote<compose::mojom::ComposeUntrustedDialog> dialog) {
  handler_receiver_.reset();
  handler_receiver_.Bind(std::move(handler));

  dialog_remote_.reset();
  dialog_remote_.Bind(std::move(dialog));
}

// TODO(b/300974056): Add histogram test for Sessions triggering CancelEdit.
void ComposeSession::LogCancelEdit() {
  session_events_.did_click_cancel_on_edit = true;
}

// ComposeSessionUntrustedPageHandler
void ComposeSession::Compose(const std::string& input,
                             compose::mojom::InputMode mode,
                             bool is_input_edited) {
  compose::ComposeRequestReason request_reason;
  if (is_input_edited) {
    session_events_.update_input_count += 1;
    request_reason = compose::ComposeRequestReason::kUpdateRequest;
  } else {
    base::RecordAction(
        base::UserMetricsAction("Compose.ComposeRequest.CreateClicked"));
    request_reason = GetRequestReasonForInputMode(mode);
  }
  optimization_guide::proto::ComposeRequest request;
  request.mutable_generate_params()->set_user_input(input);
  optimization_guide::proto::ComposeUpfrontInputMode request_mode =
      ComposeUpfrontInputMode(mode);
  request.mutable_generate_params()->set_upfront_input_mode(request_mode);

  MakeRequest(std::move(request), request_reason, is_input_edited);
}

void ComposeSession::Rewrite(compose::mojom::StyleModifier style) {
  compose::ComposeRequestReason request_reason;

  optimization_guide::proto::ComposeRequest request;
  switch (style) {
    case compose::mojom::StyleModifier::kFormal:
      request.mutable_rewrite_params()->set_tone(
          optimization_guide::proto::ComposeTone::COMPOSE_FORMAL);
      session_events_.formal_count++;
      request_reason = compose::ComposeRequestReason::kToneFormalRequest;
      break;
    case compose::mojom::StyleModifier::kCasual:
      request.mutable_rewrite_params()->set_tone(
          optimization_guide::proto::ComposeTone::COMPOSE_INFORMAL);
      session_events_.casual_count++;
      request_reason = compose::ComposeRequestReason::kToneCasualRequest;
      break;
    case compose::mojom::StyleModifier::kShorter:
      request.mutable_rewrite_params()->set_length(
          optimization_guide::proto::ComposeLength::COMPOSE_SHORTER);
      session_events_.shorten_count++;
      request_reason = compose::ComposeRequestReason::kLengthShortenRequest;
      break;
    case compose::mojom::StyleModifier::kLonger:
      request.mutable_rewrite_params()->set_length(
          optimization_guide::proto::ComposeLength::COMPOSE_LONGER);
      session_events_.lengthen_count++;
      request_reason = compose::ComposeRequestReason::kLengthElaborateRequest;
      break;
    case compose::mojom::StyleModifier::kUnset:
      // TODO: kUnset is not reachable, but a `request_reason` must be set to
      //  satisfy the compiler
    case compose::mojom::StyleModifier::kRetry:
      request.mutable_rewrite_params()->set_regenerate(true);
      session_events_.regenerate_count++;
      request_reason = compose::ComposeRequestReason::kRetryRequest;
      break;
  }
  request.mutable_rewrite_params()->set_previous_response(
      CurrentState()->mojo_state()->response->result);
  MakeRequest(std::move(request), request_reason, false);
}

// TODO(b/300974056): Add histogram test for Sessions triggering EditInput.
void ComposeSession::LogEditInput() {
  session_events_.did_click_edit = true;
}

void ComposeSession::MakeRequest(
    optimization_guide::proto::ComposeRequest request,
    compose::ComposeRequestReason request_reason,
    bool is_input_edited) {
  active_mojo_state_->has_pending_request = true;
  active_mojo_state_->feedback =
      compose::mojom::UserFeedback::kUserFeedbackUnspecified;

  // Increase Compose count regardless of status of request.
  ++session_events_.compose_requests_count;

  // TODO(b/300974056): Move this to the overall feature-enabled check.
  if (!session_ ||
      !base::FeatureList::IsEnabled(
          optimization_guide::features::kOptimizationGuideModelExecution)) {
    ProcessError(compose::EvalLocation::kServer,
                 compose::mojom::ComposeStatus::kMisconfiguration,
                 request_reason);
    return;
  }

  // Prepare the compose call, which will be invoked when all required page
  // metadata is collected.
  continue_compose_ = base::BindOnce(
      &ComposeSession::RequestWithSession, weak_ptr_factory_.GetWeakPtr(),
      std::move(request), request_reason, is_input_edited);
  // In case AX tree or page collection isn't required, we can run the
  // continuation immediately. Note that going through this call ensures we
  // populate the context object correctly.
  TryContinueComposeWithContext();
}

bool ComposeSession::HasNecessaryPageContext() const {
  return (!collect_inner_text_ || got_inner_text_) &&
         (!collect_ax_snapshot_ || got_ax_snapshot_);
}

void ComposeSession::RequestWithSession(
    const optimization_guide::proto::ComposeRequest& request,
    compose::ComposeRequestReason request_reason,
    bool is_input_edited) {
  // Add timeout for high latency Compose requests.
  const compose::Config& config = compose::GetComposeConfig();

  base::ElapsedTimer request_timer;
  request_id_++;

  auto timeout = std::make_unique<base::OneShotTimer>();
  timeout->Start(FROM_HERE, config.request_latency_timeout,
                 base::BindOnce(&ComposeSession::ComposeRequestTimeout,
                                base::Unretained(this), request_id_));
  request_timeouts_.emplace(request_id_, std::move(timeout));

  // Record the eval_location independent request metrics before model
  // execution in case request fails.
  compose::LogComposeRequestReason(request_reason);

  optimization_guide::ModelExecutionSessionCallbackWithLogging callback =
      base::BindRepeating(&ComposeSession::ModelExecutionCallback,
                          weak_ptr_factory_.GetWeakPtr(),
                          std::move(request_timer), request_id_, request_reason,
                          is_input_edited);
  optimization_guide::ExecuteModelSessionWithLogging(session_.get(), request,
                                                     callback);
}

void ComposeSession::ComposeRequestTimeout(int id) {
  request_timeouts_.erase(id);
  compose::LogComposeRequestStatus(
      is_page_language_supported_,
      compose::mojom::ComposeStatus::kRequestTimeout);

  active_mojo_state_->has_pending_request = false;
  active_mojo_state_->response = compose::mojom::ComposeResponse::New();
  active_mojo_state_->response->status =
      compose::mojom::ComposeStatus::kRequestTimeout;

  if (dialog_remote_.is_bound()) {
    dialog_remote_->ResponseReceived(active_mojo_state_->response->Clone());
  }
}

void ComposeSession::ModelExecutionCallback(
    const base::ElapsedTimer& request_timer,
    int request_id,
    compose::ComposeRequestReason request_reason,
    bool was_input_edited,
    optimization_guide::OptimizationGuideModelStreamingExecutionResult result,
    std::unique_ptr<optimization_guide::proto::ComposeLoggingData>
        logging_data) {
  base::TimeDelta request_delta = request_timer.Elapsed();
  std::unique_ptr<optimization_guide::ModelQualityLogEntry> log_entry;
  if (logging_data) {
    // There is data to log, meaning this is a complete response.
    log_entry = std::make_unique<optimization_guide::ModelQualityLogEntry>(
        model_quality_uploader_->GetWeakPtr());
    log_entry->log_ai_data_request()->mutable_compose()->MergeFrom(
        *logging_data);
  }

  compose::EvalLocation eval_location = GetEvalLocation(result);

  // Presence of the timer with the corresponding `request_id` indicates that
  // the request has not timed out - process the response. Otherwise ignore the
  // response.
  if (auto iter = request_timeouts_.find(request_id);
      iter != request_timeouts_.end()) {
    iter->second->Stop();
    // If a partial response was received, then this callback may be reused.
    // Only remove the associated timer if the response is complete.
    if (result.response.has_value() && result.response->is_complete) {
      request_timeouts_.erase(request_id);
    }
  } else {
    SetQualityLogEntryUponError(std::move(log_entry), request_delta,
                                was_input_edited);

    compose::LogComposeRequestReason(eval_location, request_reason);
    compose::LogComposeRequestStatus(
        eval_location, is_page_language_supported_,
        compose::mojom::ComposeStatus::kRequestTimeout);
    return;
  }

  // A new request has been issued, ignore this one.
  if (request_id != request_id_) {
    SetQualityLogEntryUponError(std::move(log_entry), request_delta,
                                was_input_edited);
    compose::LogComposeRequestReason(eval_location, request_reason);
    return;
  }

  if (result.response.has_value() && !result.response->is_complete) {
    ModelExecutionProgress(std::move(result.response).value());
    return;
  }

  ModelExecutionComplete(request_delta, request_reason, was_input_edited,
                         std::move(result), std::move(log_entry));
}

void ComposeSession::ModelExecutionProgress(
    optimization_guide::StreamingResponse result) {
  CHECK(base::FeatureList::IsEnabled(
      optimization_guide::features::kOptimizationGuideOnDeviceModel));
  if (!base::FeatureList::IsEnabled(
          compose::features::kComposeTextOutputAnimation)) {
    return;
  }
  if (!dialog_remote_.is_bound()) {
    return;
  }
  auto response = optimization_guide::ParsedAnyMetadata<
      optimization_guide::proto::ComposeResponse>(result.response);
  if (!response) {
    DLOG(ERROR) << "Failed to parse partial compose response";
    return;
  }
  auto partial_ui_response = compose::mojom::PartialComposeResponse::New();
  partial_ui_response->result = response->output();
  dialog_remote_->PartialResponseReceived(std::move(partial_ui_response));
}

void ComposeSession::ModelExecutionComplete(
    base::TimeDelta request_delta,
    compose::ComposeRequestReason request_reason,
    bool was_input_edited,
    optimization_guide::OptimizationGuideModelStreamingExecutionResult result,
    std::unique_ptr<optimization_guide::ModelQualityLogEntry> log_entry) {
  // Handle 'complete' results.
  active_mojo_state_->has_pending_request = false;
  compose::EvalLocation eval_location = GetEvalLocation(result);
  if (eval_location == compose::EvalLocation::kOnDevice) {
    ++session_events_.on_device_responses;
  } else {
    ++session_events_.server_responses;
  }

  compose::LogComposeRequestReason(eval_location, request_reason);

  compose::mojom::ComposeStatus status =
      ComposeStatusFromOptimizationGuideResult(result);

  if (!session_events_.session_contained_filtered_response &&
      status == compose::mojom::ComposeStatus::kFiltered) {
    session_events_.session_contained_filtered_response = true;
  }
  if (!session_events_.session_contained_any_error &&
      status != compose::mojom::ComposeStatus::kOk) {
    session_events_.session_contained_any_error = true;
  }

  if (status != compose::mojom::ComposeStatus::kOk) {
    compose::LogComposeRequestDuration(request_delta, eval_location,
                                       /* is_ok */ false);
    if (content::GetNetworkConnectionTracker()->IsOffline()) {
      ProcessError(eval_location, compose::mojom::ComposeStatus::kOffline,
                   request_reason);
    } else {
      ProcessError(eval_location, status, request_reason);
    }
    SetQualityLogEntryUponError(std::move(log_entry), request_delta,
                                was_input_edited);
    return;
  }
  CHECK(result.response->is_complete);

  auto response = optimization_guide::ParsedAnyMetadata<
      optimization_guide::proto::ComposeResponse>(result.response->response);

  if (!response) {
    compose::LogComposeRequestDuration(request_delta, eval_location,
                                       /* is_ok */ false);
    ProcessError(eval_location, compose::mojom::ComposeStatus::kNoResponse,
                 request_reason);
    SetQualityLogEntryUponError(std::move(log_entry), request_delta,
                                was_input_edited);
    return;
  }

  if (log_entry) {
    log_entry->log_ai_data_request()
        ->mutable_compose()
        ->mutable_quality()
        ->set_was_generated_via_edit(was_input_edited);
    log_entry->log_ai_data_request()
        ->mutable_compose()
        ->mutable_quality()
        ->set_started_with_proactive_nudge(
            session_events_.started_with_proactive_nudge);
    log_entry->log_ai_data_request()
        ->mutable_compose()
        ->mutable_quality()
        ->set_request_latency_ms(request_delta.InMilliseconds());
    optimization_guide::proto::Int128* token =
        log_entry->log_ai_data_request()->mutable_compose()->mutable_quality()
            ->mutable_session_id();

    token->set_high(session_id_.high());
    token->set_low(session_id_.low());
    // In the event that we are holding onto an error log upload it before it
    // gets overwritten
    if (most_recent_error_log_) {
      optimization_guide::ModelQualityLogEntry::Upload(
          std::move(most_recent_error_log_));
    }

    // if we have a valid most recent state we no longer need an error state.
    most_recent_error_log_.reset();
  }

  // Create a new ComposeState with the dialog's current mojo state and the log
  // entry just received with the response.
  std::unique_ptr<ComposeState> new_response_state =
      std::make_unique<ComposeState>(std::move(log_entry),
                                     active_mojo_state_.Clone());
  // Update the new state's mojo state to reflect the new response.
  auto ui_response = compose::mojom::ComposeResponse::New();
  ui_response->status = compose::mojom::ComposeStatus::kOk;
  ui_response->result = response->output();
  ui_response->on_device_evaluation_used = result.provided_by_on_device;
  ui_response->provided_by_user = false;
  // TODO(b/333944734): Remove undo_available and redo_available from
  // ComposeState.
  ui_response->undo_available = !history_.empty();
  ui_response->redo_available = false;
  new_response_state->mojo_state()->response = ui_response->Clone();

  // Before adding the new state to history, mark redo available on the current
  // state that will directly precede it.
  if (auto current_state = CurrentState(); current_state.has_value()) {
    current_state->mojo_state()->response->redo_available = true;
  }

  AddNewResponseToHistory(std::move(new_response_state));

  // Update `active_mojo_state_` to match the new state
  active_mojo_state_ = CurrentState()->mojo_state()->Clone();

  if (dialog_remote_.is_bound()) {
    dialog_remote_->ResponseReceived(active_mojo_state_->response->Clone());
  }

  // Log successful response status.
  compose::LogComposeRequestStatus(is_page_language_supported_,
                                   compose::mojom::ComposeStatus::kOk);
  compose::LogComposeRequestStatus(eval_location, is_page_language_supported_,
                                   compose::mojom::ComposeStatus::kOk);
  compose::LogComposeRequestDuration(request_delta, eval_location,
                                     /* is_ok */ true);
  ++session_events_.successful_requests_count;
}

void ComposeSession::AddNewResponseToHistory(
    std::unique_ptr<ComposeState> new_state) {
  // On a new response, all forward/redo states are cleared. Upload any
  // associated quality logs first.
  EraseForwardStatesInHistory();
  history_.push_back(std::move(new_state));
  history_current_index_ = history_.size() - 1;
}

void ComposeSession::EraseForwardStatesInHistory() {
  for (size_t i = history_current_index_ + 1; i < history_.size(); i++) {
    history_[i]->UploadModelQualityLogs();
  }
  if (history_.size() > history_current_index_ + 1) {
    history_.erase(history_.begin() + history_current_index_ + 1,
                   history_.end());
  }
}

void ComposeSession::ProcessError(
    compose::EvalLocation eval_location,
    compose::mojom::ComposeStatus error,
    compose::ComposeRequestReason request_reason) {
  compose::LogComposeRequestStatus(is_page_language_supported_, error);
  compose::LogComposeRequestStatus(eval_location, is_page_language_supported_,
                                   error);
  ++session_events_.failed_requests_count;

  // Feedback can not be given for a request with an error so report now.
  compose::LogComposeRequestFeedback(
      eval_location, compose::ComposeRequestFeedback::kRequestError);

  active_mojo_state_->has_pending_request = false;
  active_mojo_state_->response = compose::mojom::ComposeResponse::New();
  active_mojo_state_->response->status = error;
  active_mojo_state_->response->triggered_from_modifier =
      WasRequestTriggeredFromModifier(request_reason);

  if (dialog_remote_.is_bound()) {
    dialog_remote_->ResponseReceived(active_mojo_state_->response->Clone());
  }
}

void ComposeSession::RequestInitialState(RequestInitialStateCallback callback) {
  auto compose_config = compose::GetComposeConfig();

  std::move(callback).Run(compose::mojom::OpenMetadata::New(
      fre_complete_, current_msbb_state_, initial_input_,
      currently_has_selection_, active_mojo_state_->Clone(),
      compose::mojom::ConfigurableParams::New(compose_config.input_min_words,
                                              compose_config.input_max_words,
                                              compose_config.input_max_chars)));
}

void ComposeSession::SaveWebUIState(const std::string& webui_state) {
  active_mojo_state_->webui_state = webui_state;
}

void ComposeSession::AcceptComposeResult(
    AcceptComposeResultCallback success_callback) {
  if (callback_.is_null() || !active_mojo_state_->response ||
      active_mojo_state_->response->status !=
          compose::mojom::ComposeStatus::kOk) {
    // Guard against invoking twice before the UI is able to disconnect.
    std::move(success_callback).Run(false);
    return;
  }
  std::move(callback_).Run(
      base::UTF8ToUTF16(active_mojo_state_->response->result));
  std::move(success_callback).Run(true);
}

void ComposeSession::RecoverFromErrorState(
    RecoverFromErrorStateCallback callback) {
  // Should only be called if there is a state to return to.
  CHECK(CurrentState().has_value());
  if (!CurrentState()->IsMojoValid()) {
    // Gracefully fail if we find an invalid state.
    std::move(callback).Run(nullptr);
    return;
  }

  active_mojo_state_ = CurrentState()->mojo_state()->Clone();

  std::move(callback).Run(active_mojo_state_->Clone());
}

void ComposeSession::Undo(UndoCallback callback) {
  // Undo should only be called if a backwards saved state exists.
  if (history_current_index_ < 1) {
    std::move(callback).Run(nullptr);
    return;
  }

  auto previous_state = CurrentState(-1);
  if (!previous_state->IsMojoValid()) {
    // Gracefully fail if we find an invalid state in the history.
    std::move(callback).Run(nullptr);
    return;
  }
  history_current_index_--;
  // Only increase undo count if there are states to undo.
  session_events_.undo_count += 1;

  active_mojo_state_ = previous_state->mojo_state()->Clone();

  std::move(callback).Run(active_mojo_state_->Clone());
}

void ComposeSession::Redo(RedoCallback callback) {
  // Redo should only be called if a forward saved state exists.
  if (history_current_index_ >= history_.size() - 1) {
    std::move(callback).Run(nullptr);
    return;
  }

  auto next_state = CurrentState(1);
  if (!next_state->IsMojoValid()) {
    // Gracefully fail if we find an invalid state in the history.
    std::move(callback).Run(nullptr);
    return;
  }
  history_current_index_++;
  // Only increase redo count if there are states to redo.
  session_events_.redo_count += 1;

  active_mojo_state_ = next_state->mojo_state()->Clone();

  std::move(callback).Run(active_mojo_state_->Clone());
}

void ComposeSession::OpenBugReportingLink() {
  const char* url = kComposeBugReportURL;
  if (auto last_response_state = LastResponseState();
      last_response_state.has_value()) {
    if (last_response_state->mojo_state() &&
        last_response_state->mojo_state()
            ->response->on_device_evaluation_used) {
      url = kOnDeviceComposeBugReportURL;
    }
  }
  web_contents_->OpenURL(
      content::OpenURLParams(GURL(url), content::Referrer(),
                             WindowOpenDisposition::NEW_FOREGROUND_TAB,
                             ui::PAGE_TRANSITION_LINK,
                             /* is_renderer_initiated= */ false),
      /*navigation_handle_callback=*/{});
}

void ComposeSession::OpenComposeLearnMorePage() {
  if (base::FeatureList::IsEnabled(
          compose::features::kEnableComposeProactiveNudge)) {
    Browser* browser = chrome::FindBrowserWithTab(web_contents_);
    CHECK(browser);

    chrome::ShowSettingsSubPage(browser, chrome::kAiHelpMeWriteSubpage);
    return;
  }
  web_contents_->OpenURL(
      content::OpenURLParams(
          GURL(kComposeLearnMorePageURL), content::Referrer(),
          WindowOpenDisposition::NEW_FOREGROUND_TAB, ui::PAGE_TRANSITION_LINK,
          /* is_renderer_initiated= */ false),
      /*navigation_handle_callback=*/{});
}

void ComposeSession::OpenEnterpriseComposeLearnMorePage() {
  web_contents_->OpenURL(
      content::OpenURLParams(
          GURL(kEnterpriseComposeLearnMorePageURL), content::Referrer(),
          WindowOpenDisposition::NEW_FOREGROUND_TAB, ui::PAGE_TRANSITION_LINK,
          /* is_renderer_initiated= */ false),
      /*navigation_handle_callback=*/{});
}

void ComposeSession::OpenFeedbackSurveyLink() {
  const char* url = kComposeFeedbackSurveyURL;
  if (auto last_response_state = LastResponseState();
      last_response_state.has_value()) {
    if (last_response_state->mojo_state() &&
        last_response_state->mojo_state()
            ->response->on_device_evaluation_used) {
      url = kOnDeviceComposeFeedbackSurveyURL;
    }
  }
  web_contents_->OpenURL(
      content::OpenURLParams(GURL(url), content::Referrer(),
                             WindowOpenDisposition::NEW_FOREGROUND_TAB,
                             ui::PAGE_TRANSITION_LINK,
                             /* is_renderer_initiated= */ false),
      /*navigation_handle_callback=*/{});
}

void ComposeSession::OpenSignInPage() {
  web_contents_->OpenURL(
      content::OpenURLParams(GURL(kSignInPageURL), content::Referrer(),
                             WindowOpenDisposition::NEW_FOREGROUND_TAB,
                             ui::PAGE_TRANSITION_LINK,
                             /* is_renderer_initiated= */ false),
      /*navigation_handle_callback=*/{});
}

bool ComposeSession::CanShowFeedbackPage() {
  if (skip_feedback_ui_for_testing_) {
    return false;
  }

  OptimizationGuideKeyedService* opt_guide_keyed_service =
      OptimizationGuideKeyedServiceFactory::GetForProfile(
          Profile::FromBrowserContext(web_contents_->GetBrowserContext()));
  if (!opt_guide_keyed_service ||
      !opt_guide_keyed_service->ShouldFeatureBeCurrentlyAllowedForFeedback(
          optimization_guide::proto::LogAiDataRequest::FeatureCase::kCompose)) {
    return false;
  }

  return true;
}

void ComposeSession::OpenFeedbackPage(std::string feedback_id) {
  base::Value::Dict feedback_metadata;
  feedback_metadata.Set("log_id", feedback_id);

  chrome::ShowFeedbackPage(
      web_contents_->GetLastCommittedURL(),
      Profile::FromBrowserContext(web_contents_->GetBrowserContext()),
      feedback::kFeedbackSourceAI,
      /*description_template=*/std::string(),
      /*description_placeholder_text=*/
      l10n_util::GetStringUTF8(IDS_COMPOSE_FEEDBACK_PLACEHOLDER),
      /*category_tag=*/"compose",
      /*extra_diagnostics=*/std::string(),
      /*autofill_metadata=*/base::Value::Dict(), std::move(feedback_metadata));
}

void ComposeSession::SetUserFeedback(compose::mojom::UserFeedback feedback) {
  auto last_response_state = LastResponseState();
  if (!last_response_state.has_value() || !last_response_state->mojo_state()) {
    // If there is no recent State there is nothing that we should be applying
    // feedback to.
    return;
  }

  // Save feedback to the last state associated with a valid response.
  last_response_state->mojo_state()->feedback = feedback;
  // Update `active_mojo_state_`, as it is returned by RequestInitialState()
  // when resuming a saved session.
  if (active_mojo_state_->response) {
    active_mojo_state_->feedback = feedback;
  }
  optimization_guide::proto::UserFeedback user_feedback =
      OptimizationFeedbackFromComposeFeedback(feedback);

  // Apply feedback to the last saved state with a valid response.
  optimization_guide::proto::ComposeQuality* quality =
      last_response_state->modeling_log_entry()
          ->log_ai_data_request()
          ->mutable_compose()
          ->mutable_quality();
  if (quality) {
    quality->set_user_feedback(user_feedback);
  }
  if (feedback == compose::mojom::UserFeedback::kUserFeedbackNegative) {
    session_events_.has_thumbs_down = true;
    if (CanShowFeedbackPage()) {
      // Open the Feedback Page for a thumbs down using current request log.
      std::string feedback_id = last_response_state->modeling_log_entry()
                                    ->log_ai_data_request()
                                    ->compose()
                                    .model_execution_info()
                                    .execution_id();
      OpenFeedbackPage(feedback_id);
    }
  } else if (feedback == compose::mojom::UserFeedback::kUserFeedbackPositive) {
    session_events_.has_thumbs_up = true;
  }
}

void ComposeSession::EditResult(const std::string& new_result,
                                EditResultCallback callback) {
  // If there is no change in result text resulting from the edit, do nothing.
  if (new_result == CurrentState()->mojo_state()->response->result) {
    std::move(callback).Run(false);
    return;
  }

  // Update the active state to reflect a new edit.
  active_mojo_state_->response->result = new_result;
  active_mojo_state_->response->undo_available = true;
  active_mojo_state_->response->redo_available = false;
  active_mojo_state_->response->provided_by_user = true;
  active_mojo_state_->feedback =
      compose::mojom::UserFeedback::kUserFeedbackUnspecified;

  if (CurrentState()->is_user_edited()) {
    // The current state being edited is an edit itself. In this case, update
    // its result text instead of saving a new state.
    EraseForwardStatesInHistory();
    CurrentState()->mojo_state()->response->result = new_result;
  } else {
    // The current state being edited is a server response - save the edit as a
    // new ComposeState.
    CurrentState()->mojo_state()->response->redo_available = true;

    // Add a new ComposeState to `history_` to represent the new result edit.
    auto new_state =
        std::make_unique<ComposeState>(nullptr, active_mojo_state_.Clone());
    new_state->SetUserEdited(CurrentState()->mojo_state()->response->result);

    AddNewResponseToHistory(std::move(new_state));
  }
  std::move(callback).Run(true);
  session_events_.result_edit_count += 1;
}

void ComposeSession::InitializeWithText(std::string_view selected_text) {
  // In some cases (FRE not shown, MSBB not accepted), we wait to extract the
  // inner text until all conditions are met to enable the feature.  However, if
  // we want to extract the inner text content later, we still need to store the
  // selected text.
  initial_input_ = std::string(selected_text);
  session_events_.has_initial_text = !selected_text.empty();

  MaybeRefreshPageContext(!initial_input_.empty());
}

void ComposeSession::MaybeRefreshPageContext(bool has_selection) {
  // Update dialog state based on the current selection which can change while
  // the dialog is hidden.
  currently_has_selection_ = has_selection;

  ++session_events_.compose_dialog_open_count;

  if (!fre_complete_) {
    ++session_events_.fre_view_count;
    return;
  }
  if (!current_msbb_state_) {
    ++session_events_.msbb_view_count;
    return;
  }

  // Session is initialized at the main dialog UI state.
  ++session_events_.compose_prompt_view_count;

  RefreshInnerText();
  RefreshAXSnapshot();

  // We should only autocompose once per session
  if (has_checked_autocompose_) {
    return;
  }

  // Autocompose if it is enabled and there is a valid selection.
  if (compose::GetComposeConfig().auto_submit_with_selection &&
      IsValidComposePrompt(initial_input_)) {
    Compose(initial_input_, compose::mojom::InputMode::kUnset, false);
  }
  has_checked_autocompose_ = true;
}

void ComposeSession::UpdateInnerTextAndContinueComposeIfNecessary(
    int request_id,
    std::unique_ptr<content_extraction::InnerTextResult> result) {
  if (request_id != current_inner_text_request_id_) {
    // If this condition is hit, it means there are multiple requests for
    // inner-text in flight. Early out so that we always use the most recent
    // request.
    return;
  }
  got_inner_text_ = true;
  std::string inner_text;
  std::string trimmed_inner_text;
  std::optional<uint64_t> node_offset;
  if (result) {
    const compose::Config& config = compose::GetComposeConfig();
    inner_text = std::move(result->inner_text);
    node_offset = result->node_offset;
    if (node_offset.has_value()) {
      trimmed_inner_text = compose::GetTrimmedPageText(
          inner_text, config.trimmed_inner_text_max_chars, node_offset.value(),
          config.trimmed_inner_text_header_length);
    } else {
      trimmed_inner_text =
          inner_text.substr(0, config.trimmed_inner_text_max_chars);
    }
    compose::LogComposeDialogInnerTextSize(inner_text.size());
    if (inner_text.size() > config.inner_text_max_bytes) {
      compose::LogComposeDialogInnerTextShortenedBy(
          inner_text.size() - config.inner_text_max_bytes);
      inner_text.erase(config.inner_text_max_bytes);
    }
    compose::LogComposeDialogInnerTextOffsetFound(node_offset.has_value());
  }

  if (!session_) {
    return;
  }

  if (!page_metadata_) {
    page_metadata_.emplace();
  }

  if (node_offset.has_value()) {
    page_metadata_->set_page_inner_text_offset(node_offset.value());
  }
  page_metadata_->set_trimmed_page_inner_text(trimmed_inner_text);

  page_metadata_->set_page_inner_text(std::move(inner_text));

  TryContinueComposeWithContext();
}

void ComposeSession::UpdateAXSnapshotAndContinueComposeIfNecessary(
    int request_id,
    ui::AXTreeUpdate& update) {
  if (current_ax_snapshot_request_id_ != request_id) {
    return;
  }

  got_ax_snapshot_ = true;
  if (!page_metadata_) {
    page_metadata_.emplace();
  }

  optimization_guide::PopulateAXTreeUpdateProto(
      update, page_metadata_->mutable_ax_tree_update());

  TryContinueComposeWithContext();
}

void ComposeSession::TryContinueComposeWithContext() {
  if (!HasNecessaryPageContext() || continue_compose_.is_null()) {
    return;
  }

  if (!collect_inner_text_ && !collect_ax_snapshot_) {
    // Make sure we populate the url and title even if we're not collecting
    // other context information.
    page_metadata_.emplace();
  }

  optimization_guide::proto::ComposeRequest request;
  if (page_metadata_) {
    page_metadata_->set_page_url(web_contents_->GetLastCommittedURL().spec());
    page_metadata_->set_page_title(
        base::UTF16ToUTF8(web_contents_->GetTitle()));

    *request.mutable_page_metadata() = std::move(*page_metadata_);
    page_metadata_.reset();

    session_->AddContext(request);
  }

  std::move(continue_compose_).Run();
}

void ComposeSession::RefreshInnerText() {
  got_inner_text_ = false;
  if (!collect_inner_text_) {
    return;
  }

  ++current_inner_text_request_id_;

  inner_text_caller_->GetInnerText(
      *web_contents_->GetPrimaryMainFrame(),
      // This unsafeValue call is acceptable here because node_id is a
      // FieldRendererId which while being an U64 type is based one the int
      // DOMid which we are querying here.
      node_id_.renderer_id.GetUnsafeValue(),
      base::BindOnce(
          &ComposeSession::UpdateInnerTextAndContinueComposeIfNecessary,
          weak_ptr_factory_.GetWeakPtr(), current_inner_text_request_id_));
}

void ComposeSession::RefreshAXSnapshot() {
  got_ax_snapshot_ = false;
  if (!collect_ax_snapshot_) {
    return;
  }

  ++current_ax_snapshot_request_id_;

  web_contents_->RequestAXTreeSnapshot(
      base::BindOnce(
          &ComposeSession::UpdateAXSnapshotAndContinueComposeIfNecessary,
          weak_ptr_factory_.GetWeakPtr(), current_ax_snapshot_request_id_),
      ui::kAXModeWebContentsOnly,
      compose::GetComposeConfig().max_ax_node_count_for_page_context,
      /*timeout=*/{},
      content::WebContents::AXTreeSnapshotPolicy::kSameOriginDirectDescendants);
}

void ComposeSession::SetFirstRunCloseReason(
    compose::ComposeFreOrMsbbSessionCloseReason close_reason) {
  fre_close_reason_ = close_reason;

  if (close_reason == compose::ComposeFreOrMsbbSessionCloseReason::
                          kAckedOrAcceptedWithoutInsert) {
    if (current_msbb_state_) {
      // The FRE dialog progresses directly to the main dialog.
      session_events_.compose_prompt_view_count = 1;
      base::RecordAction(
          base::UserMetricsAction("Compose.DialogSeen.MainDialog"));
    } else {
      base::RecordAction(
          base::UserMetricsAction("Compose.DialogSeen.FirstRunMSBB"));
    }
  }
}

void ComposeSession::SetFirstRunCompleted() {
  session_events_.fre_completed_in_session = true;
  fre_complete_ = true;

  // Start inner text capture which was skipped until FRE was complete.
  MaybeRefreshPageContext(currently_has_selection_);
}

void ComposeSession::SetMSBBCloseReason(
    compose::ComposeFreOrMsbbSessionCloseReason close_reason) {
  msbb_close_reason_ = close_reason;
}

void ComposeSession::SetCloseReason(
    compose::ComposeSessionCloseReason close_reason) {
  if (close_reason == compose::ComposeSessionCloseReason::kCloseButtonPressed &&
      active_mojo_state_->has_pending_request) {
    close_reason_ =
        compose::ComposeSessionCloseReason::kCanceledBeforeResponseReceived;
  } else {
    close_reason_ = close_reason;
  }

  switch (close_reason) {
    case compose::ComposeSessionCloseReason::kCloseButtonPressed:
    case compose::ComposeSessionCloseReason::kCanceledBeforeResponseReceived:
      final_status_ = optimization_guide::proto::FinalStatus::STATUS_ABANDONED;
      final_model_status_ = optimization_guide::proto::FinalModelStatus::
          FINAL_MODEL_STATUS_FAILURE;
      session_events_.close_clicked = true;
      break;
    case compose::ComposeSessionCloseReason::kReplacedWithNewSession:
      final_status_ = optimization_guide::proto::FinalStatus::STATUS_ABANDONED;
      final_model_status_ = optimization_guide::proto::FinalModelStatus::
          FINAL_MODEL_STATUS_FAILURE;
      break;
    case compose::ComposeSessionCloseReason::kExceededMaxDuration:
    case compose::ComposeSessionCloseReason::kAbandoned:
      final_status_ = optimization_guide::proto::FinalStatus::
          STATUS_FINISHED_WITHOUT_INSERT;
      final_model_status_ = optimization_guide::proto::FinalModelStatus::
          FINAL_MODEL_STATUS_FAILURE;
      break;
    case compose::ComposeSessionCloseReason::kInsertedResponse:
      final_status_ = optimization_guide::proto::FinalStatus::STATUS_INSERTED;
      final_model_status_ = optimization_guide::proto::FinalModelStatus::
          FINAL_MODEL_STATUS_SUCCESS;
      session_events_.inserted_results = true;
      if (CurrentState().has_value() && CurrentState()->is_user_edited()) {
        session_events_.edited_result_inserted = true;
      }
      break;
    case compose::ComposeSessionCloseReason::kEndedAtFre:
    case compose::ComposeSessionCloseReason::kAckedFreEndedAtMsbb:
    case compose::ComposeSessionCloseReason::kEndedAtMsbb:
      // If the session ended during the FRE no need to set |final_status_|
      break;
  }
}

bool ComposeSession::HasExpired() {
  return session_duration_->Elapsed() >
         compose::GetComposeConfig().session_max_allowed_lifetime;
}

void ComposeSession::SetQualityLogEntryUponError(
    std::unique_ptr<optimization_guide::ModelQualityLogEntry> log_entry,
    base::TimeDelta request_time,
    bool was_input_edited) {
  if (log_entry) {
    log_entry->log_ai_data_request()
        ->mutable_compose()
        ->mutable_quality()
        ->set_request_latency_ms(request_time.InMilliseconds());
    optimization_guide::proto::Int128* token =
        log_entry->log_ai_data_request()->mutable_compose()->mutable_quality()
            ->mutable_session_id();

    token->set_high(session_id_.high());
    token->set_low(session_id_.low());

    log_entry->log_ai_data_request()
        ->mutable_compose()
        ->mutable_quality()
        ->set_was_generated_via_edit(was_input_edited);
    // In the event that we are holding onto an error log upload it before it
    // gets overwritten
    if (most_recent_error_log_) {
      optimization_guide::ModelQualityLogEntry::Upload(
          std::move(most_recent_error_log_));
    }

    most_recent_error_log_ = std::move(log_entry);
  }
}

void ComposeSession::set_current_msbb_state(bool msbb_enabled) {
  current_msbb_state_ = msbb_enabled;
  if (!msbb_enabled) {
    msbb_initially_off_ = true;
  } else if (msbb_initially_off_) {
    session_events_.msbb_enabled_in_session = true;
    SetMSBBCloseReason(compose::ComposeFreOrMsbbSessionCloseReason::
                           kAckedOrAcceptedWithoutInsert);
    base::RecordAction(
        base::UserMetricsAction("Compose.DialogSeen.MainDialog"));

    // Reset this initial state so that this block is not re-executed on every
    // subsequent dialog open.
    msbb_initially_off_ = false;
  }
}

void ComposeSession::SetSkipFeedbackUiForTesting(bool allowed) {
  skip_feedback_ui_for_testing_ = allowed;
}

void ComposeSession::LaunchHatsSurvey(
    compose::ComposeSessionCloseReason close_reason) {
  std::string trigger;
  switch (close_reason) {
    case compose::ComposeSessionCloseReason::kCloseButtonPressed:
      if (!base::FeatureList::IsEnabled(
              compose::features::kHappinessTrackingSurveysForComposeClose)) {
        return;
      }
      trigger = kHatsSurveyTriggerComposeClose;
      break;
    case compose::ComposeSessionCloseReason::kInsertedResponse:
      if (!base::FeatureList::IsEnabled(
              compose::features::
                  kHappinessTrackingSurveysForComposeAcceptance)) {
        return;
      }
      trigger = kHatsSurveyTriggerComposeAcceptance;

      break;
    default:
      return;
  }

  HatsService* hats_service = HatsServiceFactory::GetForProfile(
      Profile::FromBrowserContext(web_contents_->GetBrowserContext()),
      /*create_if_necessary=*/true);
  if (!hats_service) {
    return;
  }

  // Determine if the user used any of the response modifiers.
  bool response_modified =
      session_events_.shorten_count > 0 || session_events_.lengthen_count > 0 ||
      session_events_.formal_count > 0 || session_events_.casual_count > 0;

  SurveyBitsData product_specific_bits_data = {
      {compose::hats::HatsFields::kResponseModified, response_modified},
      {compose::hats::HatsFields::kSessionContainedFilteredResponse,
       session_events_.session_contained_filtered_response},
      {compose::hats::HatsFields::kSessionContainedError,
       session_events_.session_contained_any_error},
      {compose::hats::HatsFields::kSessionBeganWithNudge,
       session_events_.started_with_proactive_nudge}};

  std::string url = web_contents_->GetLastCommittedURL().spec();
  std::string session_id = session_id_.ToString();

  SurveyStringData product_specific_string_data = {
      {compose::hats::HatsFields::kSessionID, session_id},
      {compose::hats::HatsFields::kURL, url},
      {compose::hats::HatsFields::kLocale,
       g_browser_process->GetApplicationLocale()}};

  hats_service->LaunchSurveyForWebContents(trigger, web_contents_,
                                           product_specific_bits_data,
                                           product_specific_string_data);
}
