// Copyright 2024 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/ash/extended_updates/extended_updates_notification.h"

#include <optional>
#include <vector>

#include "ash/constants/ash_pref_names.h"
#include "ash/constants/notifier_catalogs.h"
#include "ash/constants/url_constants.h"
#include "ash/public/cpp/new_window_delegate.h"
#include "ash/public/cpp/system_notification_builder.h"
#include "ash/system/extended_updates/extended_updates_metrics.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/ash/extended_updates/extended_updates_controller.h"
#include "chrome/browser/notifications/notification_display_service.h"
#include "chrome/browser/notifications/notification_display_service_factory.h"
#include "chrome/browser/ui/webui/ash/extended_updates/extended_updates_dialog.h"
#include "chrome/grit/generated_resources.h"
#include "components/prefs/pref_service.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/chromeos/devicetype_utils.h"
#include "ui/message_center/public/cpp/notification.h"
#include "url/gurl.h"

namespace ash {

namespace {

using IndexedButton = ExtendedUpdatesNotification::IndexedButton;

// Adds the |button| to the notification via |data|,
// where |title_id| is the string resource id for the button title.
void AddButton(message_center::RichNotificationData& data,
               IndexedButton button,
               int title_id) {
  DCHECK_EQ(data.buttons.size(), static_cast<size_t>(button));
  data.buttons.emplace_back(l10n_util::GetStringUTF16(title_id));
}

}  // namespace

ExtendedUpdatesNotification::ExtendedUpdatesNotification(Profile* profile)
    : profile_(profile->GetWeakPtr()) {}

ExtendedUpdatesNotification::~ExtendedUpdatesNotification() = default;

void ExtendedUpdatesNotification::Show(Profile* profile) {
  Show(base::MakeRefCounted<ExtendedUpdatesNotification>(profile));
}

void ExtendedUpdatesNotification::Show(
    scoped_refptr<ExtendedUpdatesNotification> delegate) {
  if (!delegate || !delegate->profile()) {
    return;
  }
  Profile* profile = delegate->profile();

  delegate->SubscribeToDeviceSettingsChanges();

  message_center::RichNotificationData data;
  // Keep same order as |IndexedButton| enum.
  AddButton(data, IndexedButton::kSetUp,
            IDS_EXTENDED_UPDATES_NOTIFICATION_SETUP_BUTTON);
  AddButton(data, IndexedButton::kLearnMore,
            IDS_EXTENDED_UPDATES_NOTIFICATION_LEARN_MORE_BUTTON);

  SystemNotificationBuilder builder;
  builder.SetId(std::string(kNotificationId))
      .SetCatalogName(NotificationCatalogName::kExtendedUpdatesAvailable)
      .SetTitleId(IDS_EXTENDED_UPDATES_NOTIFICATION_TITLE)
      .SetMessageId(IDS_EXTENDED_UPDATES_NOTIFICATION_MESSAGE)
      .SetOptionalFields(data)
      .SetDelegate(std::move(delegate));
  NotificationDisplayServiceFactory::GetForProfile(profile)->Display(
      kNotificationType, builder.Build(/*keep_timestamp=*/false),
      /*metadata=*/nullptr);
  RecordExtendedUpdatesEntryPointEvent(
      ExtendedUpdatesEntryPointEvent::kNoArcNotificationShown);
}

bool ExtendedUpdatesNotification::IsNotificationDismissed(Profile* profile) {
  return profile->GetPrefs()->GetBoolean(
      prefs::kExtendedUpdatesNotificationDismissed);
}

void ExtendedUpdatesNotification::Close(bool by_user) {
  if (by_user && profile_) {
    profile_->GetPrefs()->SetBoolean(
        prefs::kExtendedUpdatesNotificationDismissed, true);
  }
}

void ExtendedUpdatesNotification::Click(
    const std::optional<int>& button_index,
    const std::optional<std::u16string>& reply) {
  if (!button_index) {
    return;
  }

  switch (IndexedButton{*button_index}) {
    case IndexedButton::kSetUp:
      RecordExtendedUpdatesEntryPointEvent(
          ExtendedUpdatesEntryPointEvent::kNoArcNotificationClicked);
      ShowExtendedUpdatesDialog();
      break;
    case IndexedButton::kLearnMore:
      OpenLearnMoreUrl();
      break;
  }

  if (profile_) {
    NotificationDisplayServiceFactory::GetForProfile(profile_.get())
        ->Close(kNotificationType, std::string(kNotificationId));
  }
}

void ExtendedUpdatesNotification::ShowExtendedUpdatesDialog() {
  extended_updates::ExtendedUpdatesDialog::Show();
}

void ExtendedUpdatesNotification::OpenLearnMoreUrl() {
  NewWindowDelegate::GetInstance()->OpenUrl(
      GURL(ash::external_urls::kDeviceExtendedUpdatesLearnMoreURL),
      NewWindowDelegate::OpenUrlFrom::kUserInteraction,
      NewWindowDelegate::Disposition::kNewForegroundTab);
}

void ExtendedUpdatesNotification::SubscribeToDeviceSettingsChanges() {
  settings_change_subscription_ =
      ExtendedUpdatesController::SubscribeToDeviceSettingsChanges(
          base::BindRepeating(
              &ExtendedUpdatesNotification::OnDeviceSettingsChanged,
              weak_factory_.GetWeakPtr()));
}

void ExtendedUpdatesNotification::OnDeviceSettingsChanged() {
  if (profile_ && ExtendedUpdatesController::Get()->IsOptedIn()) {
    NotificationDisplayServiceFactory::GetForProfile(profile_.get())
        ->Close(kNotificationType, std::string(kNotificationId));
  }
}

}  // namespace ash
