// Copyright 2014 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/policy/login/wildcard_login_checker.h"

#include <memory>

#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/values.h"
#include "chrome/browser/ash/policy/core/policy_oauth2_token_fetcher.h"
#include "components/policy/core/browser/browser_policy_connector.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"

namespace policy {

namespace {

// The oauth token consumer name.
const char kOAuthConsumerName[] = "policy_wildcard_login_checker";

// Presence of this key in the userinfo response indicates whether the user is
// on a hosted domain.
const char kHostedDomainKey[] = "hd";

}  // namespace

WildcardLoginChecker::WildcardLoginChecker(
    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
    : url_loader_factory_(std::move(url_loader_factory)) {
  CHECK(url_loader_factory_);
}

WildcardLoginChecker::~WildcardLoginChecker() = default;

void WildcardLoginChecker::StartWithRefreshToken(
    const std::string& refresh_token,
    StatusCallback callback) {
  CHECK(!token_fetcher_);
  CHECK(!user_info_fetcher_);

  callback_ = std::move(callback);

  token_fetcher_ = PolicyOAuth2TokenFetcher::CreateInstance(kOAuthConsumerName);
  token_fetcher_->StartWithRefreshToken(
      refresh_token, url_loader_factory_,
      base::BindOnce(&WildcardLoginChecker::OnPolicyTokenFetched,
                     base::Unretained(this)));
}

void WildcardLoginChecker::StartWithAccessToken(const std::string& access_token,
                                                StatusCallback callback) {
  CHECK(!token_fetcher_);
  CHECK(!user_info_fetcher_);

  callback_ = std::move(callback);

  StartUserInfoFetcher(access_token);
}

void WildcardLoginChecker::OnGetUserInfoSuccess(
    const base::DictValue& response) {
  OnCheckCompleted(response.Find(kHostedDomainKey) ? RESULT_ALLOWED
                                                   : RESULT_BLOCKED);
}

void WildcardLoginChecker::OnGetUserInfoFailure(
    const GoogleServiceAuthError& error) {
  LOG(ERROR) << "Failed to fetch user info " << error.ToString();
  OnCheckCompleted(RESULT_FAILED);
}

void WildcardLoginChecker::OnPolicyTokenFetched(
    const std::string& access_token,
    const GoogleServiceAuthError& error) {
  if (error.state() != GoogleServiceAuthError::NONE) {
    LOG(ERROR) << "Failed to fetch policy token " << error.ToString();
    OnCheckCompleted(RESULT_FAILED);
    return;
  }

  token_fetcher_.reset();
  StartUserInfoFetcher(access_token);
}

void WildcardLoginChecker::StartUserInfoFetcher(
    const std::string& access_token) {
  user_info_fetcher_ =
      std::make_unique<UserInfoFetcher>(this, url_loader_factory_);
  user_info_fetcher_->Start(access_token);
}

void WildcardLoginChecker::OnCheckCompleted(Result result) {
  if (!callback_.is_null())
    std::move(callback_).Run(result);
}

}  // namespace policy
