// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "peridot/lib/firebase_auth/firebase_auth_impl.h"

#include <utility>

#include <lib/backoff/exponential_backoff.h>
#include <lib/callback/cancellable_helper.h>
#include <lib/fit/function.h>
#include <lib/fsl/vmo/file.h>
#include <lib/fxl/functional/closure.h>
#include <lib/fxl/functional/make_copyable.h>

namespace firebase_auth {
namespace {

constexpr char kConfigBinProtoPath[] =
    "/pkg/data/firebase_auth_cobalt_config.binproto";
constexpr int32_t kCobaltAuthFailureMetricId = 3;

// Returns true if the authentication failure may be transient.
bool IsRetriableError(fuchsia::modular::auth::Status status) {
  switch (status) {
    case fuchsia::modular::auth::Status::OK:  // This should never happen.
    case fuchsia::modular::auth::Status::BAD_REQUEST:
    case fuchsia::modular::auth::Status::OAUTH_SERVER_ERROR:
    case fuchsia::modular::auth::Status::USER_CANCELLED:
      return false;
    case fuchsia::modular::auth::Status::BAD_RESPONSE:
    case fuchsia::modular::auth::Status::NETWORK_ERROR:
    case fuchsia::modular::auth::Status::INTERNAL_ERROR:
      return true;
  }
  // In case of unexpected status, retry just in case.
  return true;
}
}  // namespace

FirebaseAuthImpl::FirebaseAuthImpl(
    Config config, async_dispatcher_t* dispatcher, rng::Random* random,
    fuchsia::modular::auth::TokenProviderPtr token_provider,
    component::StartupContext* startup_context)
    : api_key_(std::move(config.api_key)),
      token_provider_(std::move(token_provider)),
      backoff_(std::make_unique<backoff::ExponentialBackoff>(
          random->NewBitGenerator<uint64_t>())),
      max_retries_(config.max_retries),
      cobalt_client_name_(std::move(config.cobalt_client_name)),
      task_runner_(dispatcher) {
  if (startup_context) {
    cobalt_logger_ = cobalt::NewCobaltLogger(dispatcher, startup_context,
                                             kConfigBinProtoPath);
  } else {
    cobalt_logger_ = nullptr;
  }
}

FirebaseAuthImpl::FirebaseAuthImpl(
    Config config, async_dispatcher_t* dispatcher,
    fuchsia::modular::auth::TokenProviderPtr token_provider,
    std::unique_ptr<backoff::Backoff> backoff,
    std::unique_ptr<cobalt::CobaltLogger> cobalt_logger)
    : api_key_(std::move(config.api_key)),
      token_provider_(std::move(token_provider)),
      backoff_(std::move(backoff)),
      max_retries_(config.max_retries),
      cobalt_client_name_(std::move(config.cobalt_client_name)),
      cobalt_logger_(std::move(cobalt_logger)),
      task_runner_(dispatcher) {}

void FirebaseAuthImpl::set_error_handler(fit::closure on_error) {
  token_provider_.set_error_handler(std::move(on_error));
}

fxl::RefPtr<callback::Cancellable> FirebaseAuthImpl::GetFirebaseToken(
    fit::function<void(AuthStatus, std::string)> callback) {
  if (api_key_.empty()) {
    FXL_LOG(WARNING) << "No Firebase API key provided. Connection to Firebase "
                        "may be unauthenticated.";
  }
  auto cancellable = callback::CancellableImpl::Create([] {});
  GetToken(max_retries_, [callback = cancellable->WrapCallback(
                              std::move(callback))](auto status, auto token) {
    callback(status, token ? token->id_token : "");
  });
  return cancellable;
}

fxl::RefPtr<callback::Cancellable> FirebaseAuthImpl::GetFirebaseUserId(
    fit::function<void(AuthStatus, std::string)> callback) {
  auto cancellable = callback::CancellableImpl::Create([] {});
  GetToken(max_retries_, [callback = cancellable->WrapCallback(
                              std::move(callback))](auto status, auto token) {
    callback(status, token ? token->local_id : "");
  });
  return cancellable;
}

void FirebaseAuthImpl::GetToken(
    int max_retries,
    fit::function<void(AuthStatus, fuchsia::modular::auth::FirebaseTokenPtr)>
        callback) {
  token_provider_->GetFirebaseAuthToken(
      api_key_,
      fxl::MakeCopyable([this, max_retries, callback = std::move(callback)](
                            fuchsia::modular::auth::FirebaseTokenPtr token,
                            fuchsia::modular::auth::AuthErr error) mutable {
        if (!token || error.status != fuchsia::modular::auth::Status::OK) {
          if (!token && error.status == fuchsia::modular::auth::Status::OK) {
            FXL_LOG(ERROR)
                << "null Firebase token returned from token provider with no "
                << "error reported. This should never happen. Retrying.";
          } else {
            FXL_LOG(ERROR)
                << "Error retrieving the Firebase token from token provider: "
                << fidl::ToUnderlying(error.status) << ", '" << error.message
                << "', retrying.";
          }

          if (max_retries > 0 && IsRetriableError(error.status)) {
            task_runner_.PostDelayedTask(
                [this, max_retries, callback = std::move(callback)]() mutable {
                  GetToken(max_retries - 1, std::move(callback));
                },
                backoff_->GetNext());
            return;
          }
        }

        backoff_->Reset();
        if (error.status == fuchsia::modular::auth::Status::OK) {
          callback(AuthStatus::OK, std::move(token));
        } else {
          ReportError(error.status);
          callback(AuthStatus::ERROR, std::move(token));
        }
      }));
}

void FirebaseAuthImpl::ReportError(fuchsia::modular::auth::Status status) {
  if (cobalt_client_name_.empty() || cobalt_logger_ == nullptr) {
    return;
  }
  cobalt_logger_->LogEventCount(kCobaltAuthFailureMetricId,
                                static_cast<uint32_t>(status),
                                cobalt_client_name_, zx::duration(0), 1);
}
}  // namespace firebase_auth
