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

#include "base/functional/callback_helpers.h"
#include "base/no_destructor.h"
#include "base/strings/strcat.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "chrome/browser/ui/browser_window/public/browser_window_features.h"
#include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
#include "chrome/browser/ui/profiles/profile_ui_test_utils.h"
#include "chrome/browser/ui/test/test_browser_ui.h"
#include "chrome/browser/ui/views/profiles/profile_management_step_controller.h"
#include "chrome/browser/ui/views/profiles/profile_picker_view_test_utils.h"
#include "chrome/browser/ui/views/profiles/profiles_pixel_test_utils.h"
#include "chrome/browser/ui/webui/signin/signin_utils.h"
#include "chrome/common/webui_url_constants.h"
#include "components/signin/public/base/signin_switches.h"
#include "content/public/browser/web_ui.h"
#include "content/public/common/content_features.h"
#include "content/public/test/browser_test.h"
#include "ui/gfx/scoped_animation_duration_scale_mode.h"
#include "ui/views/view_observer.h"

namespace {

enum class ScreenVersion {
  kOld,
  kRefreshed,
  kRevamped,
};

struct ManagedUserProfileNoticePixelTestParam {
  PixelTestParam pixel_test_param;
  ScreenVersion screen_version = ScreenVersion::kOld;
};

std::string ParamToTestSuffix(
    const testing::TestParamInfo<ManagedUserProfileNoticePixelTestParam>&
        info) {
  std::string screen_version_suffix;
  switch (info.param.screen_version) {
    case ScreenVersion::kOld:
      screen_version_suffix = "Old";
      break;
    case ScreenVersion::kRefreshed:
      screen_version_suffix = "Refreshed";
      break;
    case ScreenVersion::kRevamped:
      screen_version_suffix = "Revamped";
      break;
  }
  return base::StrCat(
      {info.param.pixel_test_param.test_suffix, screen_version_suffix});
}

std::unique_ptr<signin::EnterpriseProfileCreationDialogParams>
CreateEnterpriseProfileCreationDialogParams(AccountInfo account_info) {
  return std::make_unique<signin::EnterpriseProfileCreationDialogParams>(
      account_info,
      /*is_oidc_account=*/false,
      /*user_already_signed_in=*/false,
      /*profile_creation_required_by_policy=*/false,
      /*show_link_data_option=*/false,
      /*process_user_choice_callback=*/
      signin::SigninChoiceCallback(base::DoNothing()),
      /*done_callback=*/base::DoNothing());
}

const std::vector<ManagedUserProfileNoticePixelTestParam>& GetTestParams() {
  static const base::NoDestructor<
      std::vector<ManagedUserProfileNoticePixelTestParam>>
      params([] {
        const PixelTestParam kWindowTestParams[] = {
            {.test_suffix = "Regular"},
            {.test_suffix = "DarkTheme", .use_dark_theme = true},
            {.test_suffix = "Rtl", .use_right_to_left_language = true},
            {.test_suffix = "SmallWindow",
             .window_size = PixelTestParam::kSmallWindowSize},
        };

        std::vector<ManagedUserProfileNoticePixelTestParam> params;
        for (const auto& window_param : kWindowTestParams) {
          for (ScreenVersion screen_version :
               {ScreenVersion::kOld, ScreenVersion::kRefreshed,
                ScreenVersion::kRevamped}) {
            params.push_back({.pixel_test_param = window_param,
                              .screen_version = screen_version});
          }
        }
        return params;
      }());
  return *params;
}

// Creates a step to represent the managed-user-profile-notice.
class ManagedUserProfileNoticeStepControllerForTest
    : public ProfileManagementStepController {
 public:
  explicit ManagedUserProfileNoticeStepControllerForTest(
      ProfilePickerWebContentsHost* host,
      AccountInfo account_info,
      bool use_refreshed_ui)
      : ProfileManagementStepController(host),
        managed_user_notice_url_(
            use_refreshed_ui
                ? GURL(chrome::kChromeUIManagedUserProfileNoticeRefreshURL)
                : GURL(chrome::kChromeUIManagedUserProfileNoticeUrl)),
        account_info_(account_info) {}

  ~ManagedUserProfileNoticeStepControllerForTest() override = default;

  void Show(StepSwitchFinishedCallback step_shown_callback,
            bool reset_state) override {
    ManagedUserProfileNoticeParams::CreateForWebContents(
        host()->GetPickerContents(),
        /*browser=*/nullptr,
        ManagedUserProfileNoticeUI::ScreenType::kProfilePicker,
        CreateEnterpriseProfileCreationDialogParams(account_info_));

    // Reload the WebUI in the picker contents.
    host()->ShowScreenInPickerContents(
        managed_user_notice_url_,
        base::BindOnce(&ManagedUserProfileNoticeStepControllerForTest::
                           OnManagedUserProfileNoticeLoaded,
                       weak_ptr_factory_.GetWeakPtr(),
                       std::move(step_shown_callback)));
  }

  void OnManagedUserProfileNoticeLoaded(
      StepSwitchFinishedCallback step_shown_callback) {
    if (!step_shown_callback->is_null()) {
      std::move(step_shown_callback.value()).Run(/*success=*/true);
    }
  }

 private:
  const GURL managed_user_notice_url_;
  AccountInfo account_info_;
  base::WeakPtrFactory<ManagedUserProfileNoticeStepControllerForTest>
      weak_ptr_factory_{this};
};

}  // namespace

class ManagedUserProfileNoticeUIWindowPixelTest
    : public ProfilesPixelTestBaseT<UiBrowserTest>,
      public testing::WithParamInterface<
          ManagedUserProfileNoticePixelTestParam>,
      public views::ViewObserver {
 public:
  ManagedUserProfileNoticeUIWindowPixelTest()
      : ProfilesPixelTestBaseT<UiBrowserTest>(GetParam().pixel_test_param) {
    scoped_feature_list_.InitWithFeatureStates(
        {{switches::kFirstRunDesktopRefresh,
          GetParam().screen_version == ScreenVersion::kRefreshed ||
              GetParam().screen_version == ScreenVersion::kRevamped},
         {switches::kFirstRunDesktopRevamp,
          GetParam().screen_version == ScreenVersion::kRevamped}});
  }

  ~ManagedUserProfileNoticeUIWindowPixelTest() override {
    if (profile_picker_view_) {
      profile_picker_view_->views::View::RemoveObserver(this);
    }
  }

  void ShowUi(const std::string& name) override {
    gfx::ScopedAnimationDurationScaleMode disable_animation(
        gfx::ScopedAnimationDurationScaleMode::ZERO_DURATION);
    CHECK(browser());

    AccountInfo account_info =
        SignInWithAccount(AccountManagementStatus::kManaged);
    const bool is_ui_refresh_enabled =
        GetParam().screen_version == ScreenVersion::kRefreshed ||
        GetParam().screen_version == ScreenVersion::kRevamped;
    profile_picker_view_ = new ProfileManagementStepTestView(
        ProfilePicker::Params::ForFirstRun(browser()->GetProfile()->GetPath(),
                                           base::DoNothing()),
        ProfileManagementFlowController::Step::kPostSignInFlow,
        /*step_controller_factory=*/
        base::BindRepeating(
            [](bool use_refreshed_ui, AccountInfo account_info,
               ProfilePickerWebContentsHost* host) {
              return std::unique_ptr<ProfileManagementStepController>(
                  std::make_unique<
                      ManagedUserProfileNoticeStepControllerForTest>(
                      host, account_info, use_refreshed_ui));
            },
            is_ui_refresh_enabled, account_info));
    profile_picker_view_->views::View::AddObserver(this);
    profile_picker_view_->ShowAndWait(GetParam().pixel_test_param.window_size);
    if (ProfilePicker::GetWebViewForTesting()) {
      profiles::testing::WaitForPickerUrl(
          is_ui_refresh_enabled
              ? GURL(chrome::kChromeUIManagedUserProfileNoticeRefreshURL)
              : GURL(chrome::kChromeUIManagedUserProfileNoticeUrl));
    }
  }

  bool VerifyUi() override {
    views::Widget* widget = GetWidgetForScreenshot();

    const testing::TestInfo* test_info =
        testing::UnitTest::GetInstance()->current_test_info();
    const std::string screenshot_name =
        base::StrCat({test_info->test_suite_name(), "_", test_info->name()});

    return VerifyPixelUi(widget, "ManagedUserProfileNoticeUIWindowPixelTest",
                         screenshot_name) != ui::test::ActionResult::kFailed;
  }

  void WaitForUserDismissal() override {
    if (!profile_picker_view_) {
      return;
    }
    CHECK(GetWidgetForScreenshot());
    ViewDeletedWaiter(profile_picker_view_).Wait();
  }

  // views::ViewObserver:
  void OnViewIsDeleting(views::View* observed_view) override {
    profile_picker_view_ = nullptr;
  }

 private:
  views::Widget* GetWidgetForScreenshot() {
    if (!profile_picker_view_) {
      return nullptr;
    }
    return profile_picker_view_->GetWidget();
  }

  raw_ptr<ProfileManagementStepTestView> profile_picker_view_ = nullptr;

  base::test::ScopedFeatureList scoped_feature_list_;
};

IN_PROC_BROWSER_TEST_P(ManagedUserProfileNoticeUIWindowPixelTest,
                       InvokeUi_default) {
#if BUILDFLAG(IS_WIN)
  if (base::FeatureList::IsEnabled(features::kInitialWebUI)) {
    GTEST_SKIP() << "Skipping test because it fails with InitialWebUI enabled. "
                    "See b/477426026.";
  }
#endif

  ShowAndVerifyUi();
}

INSTANTIATE_TEST_SUITE_P(,
                         ManagedUserProfileNoticeUIWindowPixelTest,
                         testing::ValuesIn(GetTestParams()),
                         &ParamToTestSuffix);
