// Copyright 2026 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/memory/raw_ptr.h"
#include "base/test/metrics/user_action_tester.h"
#include "build/build_config.h"
#include "chrome/browser/ui/toolbar/test_toolbar_action_view_model.h"
#include "chrome/browser/ui/views/controls/hover_button_controller.h"
#include "chrome/browser/ui/views/extensions/extensions_menu_button.h"
#include "chrome/browser/ui/views/extensions/extensions_menu_item_view.h"
#include "chrome/browser/ui/views/extensions/extensions_toolbar_browsertest.h"
#include "chrome/browser/ui/views/native_widget_factory.h"
#include "content/public/test/browser_test.h"
#include "extensions/common/extension_features.h"

class ExtensionMenuItemViewBrowserTest : public ExtensionsToolbarBrowserTest {
 public:
  ExtensionMenuItemViewBrowserTest()
      : initial_extension_name_(u"Initial Extension Name"),
        initial_tooltip_(u"Initial tooltip") {
    scoped_feature_list_.InitAndDisableFeature(
        extensions_features::kExtensionsMenuAccessControl);
  }
  ExtensionMenuItemViewBrowserTest(const ExtensionMenuItemViewBrowserTest&) =
      delete;
  ExtensionMenuItemViewBrowserTest& operator=(
      const ExtensionMenuItemViewBrowserTest&) = delete;
  ~ExtensionMenuItemViewBrowserTest() override = default;

 protected:
  ExtensionsMenuButton* primary_button() { return primary_button_; }
  HoverButton* pin_button() { return pin_button_; }
  HoverButton* context_menu_button() { return context_menu_button_; }

  // ExtensionsToolbarBrowserTest:
  void SetUpOnMainThread() override;
  void TearDownOnMainThread() override;

  const std::u16string initial_extension_name_;
  const std::u16string initial_tooltip_;
  std::unique_ptr<views::Widget> widget_;
  raw_ptr<ExtensionsMenuButton> primary_button_ = nullptr;
  raw_ptr<HoverButton> pin_button_ = nullptr;
  raw_ptr<HoverButton> context_menu_button_ = nullptr;
  raw_ptr<TestToolbarActionViewModel> model_ = nullptr;

 private:
  base::test::ScopedFeatureList scoped_feature_list_;
};

void ExtensionMenuItemViewBrowserTest::SetUpOnMainThread() {
  ExtensionsToolbarBrowserTest::SetUpOnMainThread();

  widget_ = std::make_unique<views::Widget>();
  views::Widget::InitParams init_params(
      views::Widget::InitParams::CLIENT_OWNS_WIDGET,
      views::Widget::InitParams::TYPE_POPUP);
#if !BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_MAC)
  init_params.native_widget = CreateNativeWidget(
      NativeWidgetType::kDesktopNativeWidgetAura, &init_params, widget_.get());
#endif
  widget_->Init(std::move(init_params));

  auto model = std::make_unique<TestToolbarActionViewModel>("hello");
  model_ = model.get();
  model_->SetActionName(initial_extension_name_);
  model_->SetTooltip(initial_tooltip_);

  std::unique_ptr<ExtensionMenuItemView> menu_item =
      std::make_unique<ExtensionMenuItemView>(browser(), std::move(model),
                                              /*allow_pinning=*/true);

  primary_button_ = menu_item->primary_action_button_for_testing();
  pin_button_ = menu_item->pin_button_for_testing();
  context_menu_button_ = menu_item->context_menu_button_for_testing();

  widget_->SetContentsView(std::move(menu_item));
}

void ExtensionMenuItemViewBrowserTest::TearDownOnMainThread() {
  primary_button_ = nullptr;
  pin_button_ = nullptr;
  context_menu_button_ = nullptr;
  model_ = nullptr;
  widget_.reset();

  ExtensionsToolbarBrowserTest::TearDownOnMainThread();
}

IN_PROC_BROWSER_TEST_F(ExtensionMenuItemViewBrowserTest,
                       UpdatesToDisplayCorrectActionTitle) {
  EXPECT_EQ(primary_button()->label_text_for_testing(),
            initial_extension_name_);

  std::u16string extension_name = u"Extension Name";
  model_->SetActionName(extension_name);

  EXPECT_EQ(primary_button()->label_text_for_testing(), extension_name);
}

IN_PROC_BROWSER_TEST_F(ExtensionMenuItemViewBrowserTest,
                       UpdatesToDisplayTooltip) {
  EXPECT_EQ(primary_button()->GetRenderedTooltipText(gfx::Point()),
            initial_tooltip_);

  std::u16string tooltip = u"New Tooltip";
  model_->SetTooltip(tooltip);

  EXPECT_EQ(primary_button()->GetRenderedTooltipText(gfx::Point()), tooltip);
}

IN_PROC_BROWSER_TEST_F(ExtensionMenuItemViewBrowserTest,
                       ButtonMatchesEnabledStateOfExtension) {
  EXPECT_TRUE(primary_button()->GetEnabled());
  model_->SetEnabled(false);
  EXPECT_FALSE(primary_button()->GetEnabled());
  model_->SetEnabled(true);
  EXPECT_TRUE(primary_button()->GetEnabled());
}

IN_PROC_BROWSER_TEST_F(ExtensionMenuItemViewBrowserTest,
                       NotifyClickExecutesAction) {
  base::UserActionTester user_action_tester;
  constexpr char kActivatedUserAction[] =
      "Extensions.Toolbar.ExtensionActivatedFromMenu";
  EXPECT_EQ(0, model_->execute_action_count());
  EXPECT_EQ(0, user_action_tester.GetActionCount(kActivatedUserAction));

  primary_button()->SetBounds(0, 0, 100, 100);
  ClickButton(primary_button());

  EXPECT_EQ(1, model_->execute_action_count());
  EXPECT_EQ(1, user_action_tester.GetActionCount(kActivatedUserAction));
}

IN_PROC_BROWSER_TEST_F(ExtensionMenuItemViewBrowserTest, PinButtonUserAction) {
  base::UserActionTester user_action_tester;
  constexpr char kPinButtonUserAction[] = "Extensions.Toolbar.PinButtonPressed";
  EXPECT_EQ(0, user_action_tester.GetActionCount(kPinButtonUserAction));

  ClickButton(pin_button());

  EXPECT_EQ(1, user_action_tester.GetActionCount(kPinButtonUserAction));
}

IN_PROC_BROWSER_TEST_F(ExtensionMenuItemViewBrowserTest,
                       ContextMenuButtonUserAction) {
  base::UserActionTester user_action_tester;
  constexpr char kContextMenuButtonUserAction[] =
      "Extensions.Toolbar.MoreActionsButtonPressedFromMenu";
  EXPECT_EQ(0, user_action_tester.GetActionCount(kContextMenuButtonUserAction));

  ClickButton(context_menu_button());

  EXPECT_EQ(1, user_action_tester.GetActionCount(kContextMenuButtonUserAction));
}
