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

#include "content/browser/payments/payment_app_database.h"

#include <map>
#include <utility>

#include "base/base64.h"
#include "base/containers/contains.h"
#include "base/functional/bind.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "content/browser/payments/payment_app.pb.h"
#include "content/browser/payments/payment_app_context_impl.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/public/browser/browser_thread.h"
#include "third_party/blink/public/common/manifest/manifest.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/codec/png_codec.h"
#include "url/gurl.h"
#include "url/origin.h"

namespace content {
namespace {

using ::payments::mojom::PaymentDelegation;
using ::payments::mojom::PaymentHandlerStatus;
using ::payments::mojom::PaymentInstrument;
using ::payments::mojom::PaymentInstrumentPtr;

const char kPaymentAppPrefix[] = "PaymentApp:";
const char kPaymentInstrumentPrefix[] = "PaymentInstrument:";
const char kPaymentInstrumentKeyInfoPrefix[] = "PaymentInstrumentKeyInfo:";

// |pattern| is the scope URL of the service worker registration.
std::string CreatePaymentAppKey(const std::string& pattern) {
  return kPaymentAppPrefix + pattern;
}

std::string CreatePaymentInstrumentKey(const std::string& instrument_key) {
  return kPaymentInstrumentPrefix + instrument_key;
}

std::string CreatePaymentInstrumentKeyInfoKey(
    const std::string& instrument_key) {
  return kPaymentInstrumentKeyInfoPrefix + instrument_key;
}

std::map<uint64_t, std::string> ToStoredPaymentInstrumentKeyInfos(
    const std::vector<std::string>& inputs) {
  std::map<uint64_t, std::string> key_info;
  for (const auto& input : inputs) {
    StoredPaymentInstrumentKeyInfoProto key_info_proto;
    if (!key_info_proto.ParseFromString(input))
      return std::map<uint64_t, std::string>();

    key_info.insert(std::pair<uint64_t, std::string>(
        key_info_proto.insertion_order(), key_info_proto.key()));
  }

  return key_info;
}

PaymentInstrumentPtr ToPaymentInstrumentForMojo(const std::string& input) {
  StoredPaymentInstrumentProto instrument_proto;
  if (!instrument_proto.ParseFromString(input))
    return nullptr;

  PaymentInstrumentPtr instrument = PaymentInstrument::New();
  instrument->name = instrument_proto.name();
  for (const auto& icon_proto : instrument_proto.icons()) {
    blink::Manifest::ImageResource icon;
    icon.src = GURL(icon_proto.src());
    icon.type = base::UTF8ToUTF16(icon_proto.type());
    for (const auto& size_proto : icon_proto.sizes()) {
      icon.sizes.emplace_back(size_proto.width(), size_proto.height());
    }
    instrument->icons.emplace_back(icon);
  }
  instrument->method = instrument_proto.method();

  return instrument;
}

SupportedDelegations ToSupportedDelegations(
    const content::SupportedDelegationsProto& supported_delegations_proto) {
  SupportedDelegations supported_delegations;
  if (supported_delegations_proto.has_shipping_address()) {
    supported_delegations.shipping_address =
        supported_delegations_proto.shipping_address();
  }
  if (supported_delegations_proto.has_payer_name()) {
    supported_delegations.payer_name = supported_delegations_proto.payer_name();
  }
  if (supported_delegations_proto.has_payer_email()) {
    supported_delegations.payer_email =
        supported_delegations_proto.payer_email();
  }
  if (supported_delegations_proto.has_payer_phone()) {
    supported_delegations.payer_phone =
        supported_delegations_proto.payer_phone();
  }

  return supported_delegations;
}

std::unique_ptr<StoredPaymentApp> ToStoredPaymentApp(const std::string& input) {
  StoredPaymentAppProto app_proto;
  if (!app_proto.ParseFromString(input))
    return nullptr;

  std::unique_ptr<StoredPaymentApp> app = std::make_unique<StoredPaymentApp>();
  app->registration_id = app_proto.registration_id();
  app->scope = GURL(app_proto.scope());
  app->name = app_proto.name();
  app->prefer_related_applications = app_proto.prefer_related_applications();
  for (const auto& related_app : app_proto.related_applications()) {
    app->related_applications.emplace_back(StoredRelatedApplication());
    app->related_applications.back().platform = related_app.platform();
    app->related_applications.back().id = related_app.id();
  }
  app->user_hint = app_proto.user_hint();
  app->supported_delegations =
      ToSupportedDelegations(app_proto.supported_delegations());

  if (!app_proto.icon().empty()) {
    std::optional<std::vector<uint8_t>> icon_raw_data =
        base::Base64Decode(app_proto.icon());
    app->icon = std::make_unique<SkBitmap>();
    // Note that the icon has been decoded to PNG raw data regardless of the
    // original icon format that was downloaded.
    *app->icon = gfx::PNGCodec::Decode(icon_raw_data.value());
    CHECK(!app->icon->isNull());
  }

  return app;
}

}  // namespace

PaymentAppDatabase::PaymentAppDatabase(
    scoped_refptr<ServiceWorkerContextWrapper> service_worker_context)
    : service_worker_context_(service_worker_context) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
}

PaymentAppDatabase::~PaymentAppDatabase() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
}

void PaymentAppDatabase::ReadAllPaymentApps(
    ReadAllPaymentAppsCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  service_worker_context_->GetUserDataForAllRegistrationsByKeyPrefix(
      kPaymentAppPrefix,
      base::BindOnce(&PaymentAppDatabase::DidReadAllPaymentApps,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void PaymentAppDatabase::DeletePaymentInstrument(
    const GURL& scope,
    const std::string& instrument_key,
    DeletePaymentInstrumentCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // TODO(crbug.com/40177656): Update this when PaymentManager
  // implements StorageKey.
  service_worker_context_->FindReadyRegistrationForScope(
      scope, blink::StorageKey::CreateFirstParty(url::Origin::Create(scope)),
      base::BindOnce(
          &PaymentAppDatabase::DidFindRegistrationToDeletePaymentInstrument,
          weak_ptr_factory_.GetWeakPtr(), instrument_key, std::move(callback)));
}

void PaymentAppDatabase::ReadPaymentInstrument(
    const GURL& scope,
    const std::string& instrument_key,
    ReadPaymentInstrumentCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // TODO(crbug.com/40177656): Update this when PaymentManager
  // implements StorageKey.
  service_worker_context_->FindReadyRegistrationForScope(
      scope, blink::StorageKey::CreateFirstParty(url::Origin::Create(scope)),
      base::BindOnce(
          &PaymentAppDatabase::DidFindRegistrationToReadPaymentInstrument,
          weak_ptr_factory_.GetWeakPtr(), instrument_key, std::move(callback)));
}

void PaymentAppDatabase::KeysOfPaymentInstruments(
    const GURL& scope,
    KeysOfPaymentInstrumentsCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // TODO(crbug.com/40177656): Update this when PaymentManager
  // implements StorageKey.
  service_worker_context_->FindReadyRegistrationForScope(
      scope, blink::StorageKey::CreateFirstParty(url::Origin::Create(scope)),
      base::BindOnce(&PaymentAppDatabase::DidFindRegistrationToGetKeys,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void PaymentAppDatabase::HasPaymentInstrument(
    const GURL& scope,
    const std::string& instrument_key,
    HasPaymentInstrumentCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // TODO(crbug.com/40177656): Update this when PaymentManager
  // implements StorageKey.
  service_worker_context_->FindReadyRegistrationForScope(
      scope, blink::StorageKey::CreateFirstParty(url::Origin::Create(scope)),
      base::BindOnce(
          &PaymentAppDatabase::DidFindRegistrationToHasPaymentInstrument,
          weak_ptr_factory_.GetWeakPtr(), instrument_key, std::move(callback)));
}

void PaymentAppDatabase::WritePaymentInstrument(
    const GURL& scope,
    const std::string& instrument_key,
    PaymentInstrumentPtr instrument,
    WritePaymentInstrumentCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // TODO(crbug.com/40177656): Update this when PaymentManager
  // implements StorageKey.
  if (instrument->icons.size() > 0) {
    std::vector<blink::Manifest::ImageResource> icons(instrument->icons);
    PaymentInstrumentIconFetcher::Start(
        scope,
        service_worker_context_->GetWindowClientFrameRoutingIds(
            blink::StorageKey::CreateFirstParty(url::Origin::Create(scope))),
        icons,
        base::BindOnce(&PaymentAppDatabase::DidFetchedPaymentInstrumentIcon,
                       weak_ptr_factory_.GetWeakPtr(), scope, instrument_key,
                       std::move(instrument), std::move(callback)));
  } else {
    service_worker_context_->FindReadyRegistrationForScope(
        scope, blink::StorageKey::CreateFirstParty(url::Origin::Create(scope)),
        base::BindOnce(
            &PaymentAppDatabase::DidFindRegistrationToWritePaymentInstrument,
            weak_ptr_factory_.GetWeakPtr(), instrument_key,
            std::move(instrument), std::string(), std::move(callback)));
  }
}

void PaymentAppDatabase::DidFetchedPaymentInstrumentIcon(
    const GURL& scope,
    const std::string& instrument_key,
    payments::mojom::PaymentInstrumentPtr instrument,
    WritePaymentInstrumentCallback callback,
    const std::string& icon) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (icon.empty()) {
    std::move(callback).Run(PaymentHandlerStatus::FETCH_INSTRUMENT_ICON_FAILED);
    return;
  }

  // TODO(crbug.com/40177656): Update this when PaymentManager
  // implements StorageKey.
  service_worker_context_->FindReadyRegistrationForScope(
      scope, blink::StorageKey::CreateFirstParty(url::Origin::Create(scope)),
      base::BindOnce(
          &PaymentAppDatabase::DidFindRegistrationToWritePaymentInstrument,
          weak_ptr_factory_.GetWeakPtr(), instrument_key, std::move(instrument),
          icon, std::move(callback)));
}

void PaymentAppDatabase::FetchAndUpdatePaymentAppInfo(
    const GURL& context,
    const GURL& scope,
    FetchAndUpdatePaymentAppInfoCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  PaymentAppInfoFetcher::Start(
      context, service_worker_context_,
      base::BindOnce(&PaymentAppDatabase::FetchPaymentAppInfoCallback,
                     weak_ptr_factory_.GetWeakPtr(), scope,
                     std::move(callback)));
}

void PaymentAppDatabase::FetchPaymentAppInfoCallback(
    const GURL& scope,
    FetchAndUpdatePaymentAppInfoCallback callback,
    std::unique_ptr<PaymentAppInfoFetcher::PaymentAppInfo> app_info) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // TODO(crbug.com/40177656): Update this when PaymentManager
  // implements StorageKey.
  service_worker_context_->FindReadyRegistrationForScope(
      scope, blink::StorageKey::CreateFirstParty(url::Origin::Create(scope)),
      base::BindOnce(
          &PaymentAppDatabase::DidFindRegistrationToUpdatePaymentAppInfo,
          weak_ptr_factory_.GetWeakPtr(), std::move(callback),
          std::move(app_info)));
}

void PaymentAppDatabase::DidFindRegistrationToUpdatePaymentAppInfo(
    FetchAndUpdatePaymentAppInfoCallback callback,
    std::unique_ptr<PaymentAppInfoFetcher::PaymentAppInfo> app_info,
    blink::ServiceWorkerStatusCode status,
    scoped_refptr<ServiceWorkerRegistration> registration) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (status != blink::ServiceWorkerStatusCode::kOk) {
    std::move(callback).Run(PaymentHandlerStatus::NO_ACTIVE_WORKER);
    return;
  }

  service_worker_context_->GetRegistrationUserDataByKeyPrefix(
      registration->id(), CreatePaymentAppKey(registration->scope().spec()),
      base::BindOnce(
          &PaymentAppDatabase::DidGetPaymentAppInfoToUpdatePaymentAppInfo,
          weak_ptr_factory_.GetWeakPtr(), std::move(callback),
          std::move(app_info), registration));
}

void PaymentAppDatabase::DidGetPaymentAppInfoToUpdatePaymentAppInfo(
    FetchAndUpdatePaymentAppInfoCallback callback,
    std::unique_ptr<PaymentAppInfoFetcher::PaymentAppInfo> app_info,
    scoped_refptr<ServiceWorkerRegistration> registration,
    const std::vector<std::string>& data,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (status != blink::ServiceWorkerStatusCode::kOk) {
    std::move(callback).Run(PaymentHandlerStatus::NO_ACTIVE_WORKER);
    return;
  }

  DCHECK_LE(data.size(), 1U);
  StoredPaymentAppProto payment_app_proto;
  if (data.size() == 1U) {
    payment_app_proto.ParseFromString(data[0]);
  }
  payment_app_proto.set_registration_id(registration->id());
  payment_app_proto.set_scope(registration->scope().spec());
  // Do not override name and icon if they are invalid.
  if (!app_info->name.empty()) {
    payment_app_proto.set_name(app_info->name);
  }
  if (!app_info->icon.empty()) {
    payment_app_proto.set_icon(app_info->icon);
  }
  payment_app_proto.set_prefer_related_applications(
      app_info->prefer_related_applications);
  for (const auto& related_app : app_info->related_applications) {
    StoredRelatedApplicationProto* related_app_proto =
        payment_app_proto.add_related_applications();
    related_app_proto->set_platform(related_app.platform);
    related_app_proto->set_id(related_app.id);
  }

  std::string serialized_payment_app;
  bool success = payment_app_proto.SerializeToString(&serialized_payment_app);
  DCHECK(success);

  service_worker_context_->StoreRegistrationUserData(
      registration->id(), registration->key(),
      {{CreatePaymentAppKey(registration->scope().spec()),
        serialized_payment_app}},
      base::BindOnce(&PaymentAppDatabase::DidUpdatePaymentApp,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback),
                     app_info->name.empty() || app_info->icon.empty()));
}

void PaymentAppDatabase::DidUpdatePaymentApp(
    FetchAndUpdatePaymentAppInfoCallback callback,
    bool fetch_app_info_failed,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  PaymentHandlerStatus handler_status =
      fetch_app_info_failed
          ? PaymentHandlerStatus::FETCH_PAYMENT_APP_INFO_FAILED
          : PaymentHandlerStatus::SUCCESS;
  handler_status = status == blink::ServiceWorkerStatusCode::kOk
                       ? handler_status
                       : PaymentHandlerStatus::STORAGE_OPERATION_FAILED;
  return std::move(callback).Run(handler_status);
}

void PaymentAppDatabase::ClearPaymentInstruments(
    const GURL& scope,
    ClearPaymentInstrumentsCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // TODO(crbug.com/40177656): Update this when PaymentManager
  // implements StorageKey.
  service_worker_context_->FindReadyRegistrationForScope(
      scope, blink::StorageKey::CreateFirstParty(url::Origin::Create(scope)),
      base::BindOnce(
          &PaymentAppDatabase::DidFindRegistrationToClearPaymentInstruments,
          weak_ptr_factory_.GetWeakPtr(), scope, std::move(callback)));
}

void PaymentAppDatabase::SetPaymentAppUserHint(const GURL& scope,
                                               const std::string& user_hint) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // TODO(crbug.com/40177656): Update this when PaymentManager
  // implements StorageKey.
  service_worker_context_->FindReadyRegistrationForScope(
      scope, blink::StorageKey::CreateFirstParty(url::Origin::Create(scope)),
      base::BindOnce(
          &PaymentAppDatabase::DidFindRegistrationToSetPaymentAppUserHint,
          weak_ptr_factory_.GetWeakPtr(), user_hint));
}

void PaymentAppDatabase::EnablePaymentAppDelegations(
    const GURL& scope,
    const std::vector<PaymentDelegation>& delegations,
    EnableDelegationsCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // TODO(crbug.com/40177656): Update this when PaymentManager
  // implements StorageKey.
  service_worker_context_->FindReadyRegistrationForScope(
      scope, blink::StorageKey::CreateFirstParty(url::Origin::Create(scope)),
      base::BindOnce(
          &PaymentAppDatabase::DidFindRegistrationToEnablePaymentAppDelegations,
          weak_ptr_factory_.GetWeakPtr(), delegations, std::move(callback)));
}

void PaymentAppDatabase::DidFindRegistrationToEnablePaymentAppDelegations(
    const std::vector<PaymentDelegation>& delegations,
    EnableDelegationsCallback callback,
    blink::ServiceWorkerStatusCode status,
    scoped_refptr<ServiceWorkerRegistration> registration) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (status != blink::ServiceWorkerStatusCode::kOk) {
    std::move(callback).Run(PaymentHandlerStatus::NO_ACTIVE_WORKER);
    return;
  }

  // Constructing registration_id and payment_app_key before
  // moving registration.
  int64_t registration_id = registration->id();
  std::string payment_app_key =
      CreatePaymentAppKey(registration->scope().spec());
  service_worker_context_->GetRegistrationUserDataByKeyPrefix(
      registration_id, payment_app_key,
      base::BindOnce(
          &PaymentAppDatabase::DidGetPaymentAppInfoToEnableDelegations,
          weak_ptr_factory_.GetWeakPtr(), delegations, std::move(callback),
          std::move(registration)));
}

void PaymentAppDatabase::DidGetPaymentAppInfoToEnableDelegations(
    const std::vector<PaymentDelegation>& delegations,
    EnableDelegationsCallback callback,
    scoped_refptr<ServiceWorkerRegistration> registration,
    const std::vector<std::string>& data,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (status != blink::ServiceWorkerStatusCode::kOk) {
    std::move(callback).Run(PaymentHandlerStatus::NOT_FOUND);
    return;
  }

  DCHECK_LE(data.size(), 1U);
  StoredPaymentAppProto app_proto;
  if (data.size() == 1U) {
    app_proto.ParseFromString(data[0]);
  }

  auto supported_delegations_proto =
      std::make_unique<SupportedDelegationsProto>();
  for (auto delegation : delegations) {
    switch (delegation) {
      case PaymentDelegation::SHIPPING_ADDRESS:
        supported_delegations_proto->set_shipping_address(true);
        break;
      case PaymentDelegation::PAYER_NAME:
        supported_delegations_proto->set_payer_name(true);
        break;
      case PaymentDelegation::PAYER_PHONE:
        supported_delegations_proto->set_payer_phone(true);
        break;
      case PaymentDelegation::PAYER_EMAIL:
        supported_delegations_proto->set_payer_email(true);
        break;
    }
  }
  app_proto.set_allocated_supported_delegations(
      supported_delegations_proto.release());

  std::string serialized_payment_app;
  bool success = app_proto.SerializeToString(&serialized_payment_app);
  DCHECK(success);

  service_worker_context_->StoreRegistrationUserData(
      registration->id(), registration->key(),
      {{CreatePaymentAppKey(registration->scope().spec()),
        serialized_payment_app}},
      base::BindOnce(&PaymentAppDatabase::DidEnablePaymentAppDelegations,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void PaymentAppDatabase::DidEnablePaymentAppDelegations(
    EnableDelegationsCallback callback,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  return std::move(callback).Run(
      status == blink::ServiceWorkerStatusCode::kOk
          ? PaymentHandlerStatus::SUCCESS
          : PaymentHandlerStatus::STORAGE_OPERATION_FAILED);
}

void PaymentAppDatabase::DidFindRegistrationToSetPaymentAppUserHint(
    const std::string& user_hint,
    blink::ServiceWorkerStatusCode status,
    scoped_refptr<ServiceWorkerRegistration> registration) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (status != blink::ServiceWorkerStatusCode::kOk)
    return;

  // Constructing registration_id and payment_app_key before
  // moving registration.
  int64_t registration_id = registration->id();
  std::string payment_app_key =
      CreatePaymentAppKey(registration->scope().spec());
  service_worker_context_->GetRegistrationUserDataByKeyPrefix(
      registration_id, payment_app_key,
      base::BindOnce(&PaymentAppDatabase::DidGetPaymentAppInfoToSetUserHint,
                     weak_ptr_factory_.GetWeakPtr(), user_hint,
                     std::move(registration)));
}

void PaymentAppDatabase::DidGetPaymentAppInfoToSetUserHint(
    const std::string& user_hint,
    scoped_refptr<ServiceWorkerRegistration> registration,
    const std::vector<std::string>& data,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (status != blink::ServiceWorkerStatusCode::kOk)
    return;

  DCHECK_LE(data.size(), 1U);
  StoredPaymentAppProto app_proto;
  if (data.size() == 1U) {
    app_proto.ParseFromString(data[0]);
  }
  app_proto.set_user_hint(user_hint);

  std::string serialized_payment_app;
  bool success = app_proto.SerializeToString(&serialized_payment_app);
  DCHECK(success);

  service_worker_context_->StoreRegistrationUserData(
      registration->id(), registration->key(),
      {{CreatePaymentAppKey(registration->scope().spec()),
        serialized_payment_app}},
      base::BindOnce(&PaymentAppDatabase::DidSetPaymentAppUserHint,
                     weak_ptr_factory_.GetWeakPtr()));
}

void PaymentAppDatabase::DidSetPaymentAppUserHint(
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(status == blink::ServiceWorkerStatusCode::kOk);
}

void PaymentAppDatabase::SetPaymentAppInfoForRegisteredServiceWorker(
    int64_t registration_id,
    const std::string& instrument_key,
    const std::string& name,
    const std::string& icon,
    const std::string& method,
    const SupportedDelegations& supported_delegations,
    SetPaymentAppInfoCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  service_worker_context_->FindReadyRegistrationForIdOnly(
      registration_id,
      base::BindOnce(&PaymentAppDatabase::DidFindRegistrationToSetPaymentApp,
                     weak_ptr_factory_.GetWeakPtr(), instrument_key, name, icon,
                     method, supported_delegations, std::move(callback)));
}

void PaymentAppDatabase::DidFindRegistrationToSetPaymentApp(
    const std::string& instrument_key,
    const std::string& name,
    const std::string& icon,
    const std::string& method,
    const SupportedDelegations& supported_delegations,
    SetPaymentAppInfoCallback callback,
    blink::ServiceWorkerStatusCode status,
    scoped_refptr<ServiceWorkerRegistration> registration) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (status != blink::ServiceWorkerStatusCode::kOk) {
    std::move(callback).Run(PaymentHandlerStatus::NO_ACTIVE_WORKER);
    return;
  }

  StoredPaymentAppProto payment_app_proto;
  payment_app_proto.set_registration_id(registration->id());
  payment_app_proto.set_scope(registration->scope().spec());
  payment_app_proto.set_name(name);
  payment_app_proto.set_icon(icon);

  // Set supported delegations.
  auto supported_delegations_proto =
      std::make_unique<SupportedDelegationsProto>();
  supported_delegations_proto->set_shipping_address(
      supported_delegations.shipping_address);
  supported_delegations_proto->set_payer_name(supported_delegations.payer_name);
  supported_delegations_proto->set_payer_phone(
      supported_delegations.payer_phone);
  supported_delegations_proto->set_payer_email(
      supported_delegations.payer_email);
  payment_app_proto.set_allocated_supported_delegations(
      supported_delegations_proto.release());

  std::string serialized_payment_app;
  bool success = payment_app_proto.SerializeToString(&serialized_payment_app);
  DCHECK(success);

  // Constructing registration_id, registration_key and storage_key before
  // moving registration.
  int64_t registration_id = registration->id();
  blink::StorageKey registration_key = registration->key();
  std::string storage_key = CreatePaymentAppKey(registration->scope().spec());
  service_worker_context_->StoreRegistrationUserData(
      registration_id, registration_key,
      {{storage_key, serialized_payment_app}},
      base::BindOnce(&PaymentAppDatabase::DidWritePaymentAppForSetPaymentApp,
                     weak_ptr_factory_.GetWeakPtr(), instrument_key, method,
                     std::move(callback), std::move(registration)));

  return;
}

void PaymentAppDatabase::DidWritePaymentAppForSetPaymentApp(
    const std::string& instrument_key,
    const std::string& method,
    SetPaymentAppInfoCallback callback,
    scoped_refptr<ServiceWorkerRegistration> registration,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (status != blink::ServiceWorkerStatusCode::kOk) {
    std::move(callback).Run(PaymentHandlerStatus::STORAGE_OPERATION_FAILED);
    return;
  }

  StoredPaymentInstrumentProto instrument_proto;
  instrument_proto.set_registration_id(registration->id());
  instrument_proto.set_instrument_key(instrument_key);
  instrument_proto.set_method(method);

  std::string serialized_instrument;
  bool success = instrument_proto.SerializeToString(&serialized_instrument);
  DCHECK(success);

  StoredPaymentInstrumentKeyInfoProto key_info_proto;
  key_info_proto.set_key(instrument_key);
  key_info_proto.set_insertion_order(base::Time::Now().ToInternalValue());

  std::string serialized_key_info;
  success = key_info_proto.SerializeToString(&serialized_key_info);
  DCHECK(success);

  service_worker_context_->StoreRegistrationUserData(
      registration->id(), registration->key(),
      {{CreatePaymentInstrumentKey(instrument_key), serialized_instrument},
       {CreatePaymentInstrumentKeyInfoKey(instrument_key),
        serialized_key_info}},
      base::BindOnce(
          &PaymentAppDatabase::DidWritePaymentInstrumentForSetPaymentApp,
          weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void PaymentAppDatabase::DidWritePaymentInstrumentForSetPaymentApp(
    SetPaymentAppInfoCallback callback,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  return std::move(callback).Run(
      status == blink::ServiceWorkerStatusCode::kOk
          ? PaymentHandlerStatus::SUCCESS
          : PaymentHandlerStatus::STORAGE_OPERATION_FAILED);
}

void PaymentAppDatabase::DidReadAllPaymentApps(
    ReadAllPaymentAppsCallback callback,
    const std::vector<std::pair<int64_t, std::string>>& raw_data,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (status != blink::ServiceWorkerStatusCode::kOk) {
    std::move(callback).Run(PaymentApps());
    return;
  }

  PaymentApps apps;
  for (const auto& item_of_raw_data : raw_data) {
    std::unique_ptr<StoredPaymentApp> app =
        ToStoredPaymentApp(item_of_raw_data.second);
    if (app)
      apps[app->registration_id] = std::move(app);
  }

  if (apps.size() == 0U) {
    std::move(callback).Run(PaymentApps());
    return;
  }

  service_worker_context_->GetUserDataForAllRegistrationsByKeyPrefix(
      kPaymentInstrumentPrefix,
      base::BindOnce(&PaymentAppDatabase::DidReadAllPaymentInstruments,
                     weak_ptr_factory_.GetWeakPtr(), std::move(apps),
                     std::move(callback)));
}

void PaymentAppDatabase::DidReadAllPaymentInstruments(
    PaymentApps apps,
    ReadAllPaymentAppsCallback callback,
    const std::vector<std::pair<int64_t, std::string>>& raw_data,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (status != blink::ServiceWorkerStatusCode::kOk) {
    std::move(callback).Run(PaymentApps());
    return;
  }

  for (const auto& item_of_raw_data : raw_data) {
    StoredPaymentInstrumentProto instrument_proto;
    if (!instrument_proto.ParseFromString(item_of_raw_data.second))
      continue;

    int64_t id = instrument_proto.registration_id();
    if (!base::Contains(apps, id))
      continue;

    apps[id]->enabled_methods.emplace_back(instrument_proto.method());
  }

  std::move(callback).Run(std::move(apps));
}

void PaymentAppDatabase::DidFindRegistrationToDeletePaymentInstrument(
    const std::string& instrument_key,
    DeletePaymentInstrumentCallback callback,
    blink::ServiceWorkerStatusCode status,
    scoped_refptr<ServiceWorkerRegistration> registration) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (status != blink::ServiceWorkerStatusCode::kOk) {
    std::move(callback).Run(PaymentHandlerStatus::NO_ACTIVE_WORKER);
    return;
  }

  service_worker_context_->GetRegistrationUserData(
      registration->id(), {CreatePaymentInstrumentKey(instrument_key)},
      base::BindOnce(&PaymentAppDatabase::DidFindPaymentInstrument,
                     weak_ptr_factory_.GetWeakPtr(), registration->id(),
                     instrument_key, std::move(callback)));
}

void PaymentAppDatabase::DidFindPaymentInstrument(
    int64_t registration_id,
    const std::string& instrument_key,
    DeletePaymentInstrumentCallback callback,
    const std::vector<std::string>& data,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (status != blink::ServiceWorkerStatusCode::kOk || data.size() != 1) {
    std::move(callback).Run(PaymentHandlerStatus::NOT_FOUND);
    return;
  }

  service_worker_context_->ClearRegistrationUserData(
      registration_id,
      {CreatePaymentInstrumentKey(instrument_key),
       CreatePaymentInstrumentKeyInfoKey(instrument_key)},
      base::BindOnce(&PaymentAppDatabase::DidDeletePaymentInstrument,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void PaymentAppDatabase::DidDeletePaymentInstrument(
    DeletePaymentInstrumentCallback callback,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  return std::move(callback).Run(status == blink::ServiceWorkerStatusCode::kOk
                                     ? PaymentHandlerStatus::SUCCESS
                                     : PaymentHandlerStatus::NOT_FOUND);
}

void PaymentAppDatabase::DidFindRegistrationToReadPaymentInstrument(
    const std::string& instrument_key,
    ReadPaymentInstrumentCallback callback,
    blink::ServiceWorkerStatusCode status,
    scoped_refptr<ServiceWorkerRegistration> registration) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (status != blink::ServiceWorkerStatusCode::kOk) {
    std::move(callback).Run(PaymentInstrument::New(),
                            PaymentHandlerStatus::NO_ACTIVE_WORKER);
    return;
  }

  service_worker_context_->GetRegistrationUserData(
      registration->id(), {CreatePaymentInstrumentKey(instrument_key)},
      base::BindOnce(&PaymentAppDatabase::DidReadPaymentInstrument,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void PaymentAppDatabase::DidReadPaymentInstrument(
    ReadPaymentInstrumentCallback callback,
    const std::vector<std::string>& data,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (status != blink::ServiceWorkerStatusCode::kOk || data.size() != 1) {
    std::move(callback).Run(PaymentInstrument::New(),
                            PaymentHandlerStatus::NOT_FOUND);
    return;
  }

  PaymentInstrumentPtr instrument = ToPaymentInstrumentForMojo(data[0]);
  if (!instrument) {
    std::move(callback).Run(PaymentInstrument::New(),
                            PaymentHandlerStatus::STORAGE_OPERATION_FAILED);
    return;
  }

  std::move(callback).Run(std::move(instrument), PaymentHandlerStatus::SUCCESS);
}

void PaymentAppDatabase::DidFindRegistrationToGetKeys(
    KeysOfPaymentInstrumentsCallback callback,
    blink::ServiceWorkerStatusCode status,
    scoped_refptr<ServiceWorkerRegistration> registration) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (status != blink::ServiceWorkerStatusCode::kOk) {
    std::move(callback).Run(std::vector<std::string>(),
                            PaymentHandlerStatus::NO_ACTIVE_WORKER);
    return;
  }

  service_worker_context_->GetRegistrationUserDataByKeyPrefix(
      registration->id(), {kPaymentInstrumentKeyInfoPrefix},
      base::BindOnce(&PaymentAppDatabase::DidGetKeysOfPaymentInstruments,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void PaymentAppDatabase::DidGetKeysOfPaymentInstruments(
    KeysOfPaymentInstrumentsCallback callback,
    const std::vector<std::string>& data,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (status != blink::ServiceWorkerStatusCode::kOk) {
    std::move(callback).Run(std::vector<std::string>(),
                            PaymentHandlerStatus::NOT_FOUND);
    return;
  }

  std::vector<std::string> keys;
  for (const auto& key_info : ToStoredPaymentInstrumentKeyInfos(data)) {
    keys.push_back(key_info.second);
  }

  std::move(callback).Run(keys, PaymentHandlerStatus::SUCCESS);
}

void PaymentAppDatabase::DidFindRegistrationToHasPaymentInstrument(
    const std::string& instrument_key,
    HasPaymentInstrumentCallback callback,
    blink::ServiceWorkerStatusCode status,
    scoped_refptr<ServiceWorkerRegistration> registration) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (status != blink::ServiceWorkerStatusCode::kOk) {
    std::move(callback).Run(PaymentHandlerStatus::NO_ACTIVE_WORKER);
    return;
  }

  service_worker_context_->GetRegistrationUserData(
      registration->id(), {CreatePaymentInstrumentKey(instrument_key)},
      base::BindOnce(&PaymentAppDatabase::DidHasPaymentInstrument,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void PaymentAppDatabase::DidHasPaymentInstrument(
    DeletePaymentInstrumentCallback callback,
    const std::vector<std::string>& data,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (status != blink::ServiceWorkerStatusCode::kOk || data.size() != 1) {
    std::move(callback).Run(PaymentHandlerStatus::NOT_FOUND);
    return;
  }

  std::move(callback).Run(PaymentHandlerStatus::SUCCESS);
}

void PaymentAppDatabase::DidFindRegistrationToWritePaymentInstrument(
    const std::string& instrument_key,
    PaymentInstrumentPtr instrument,
    const std::string& decoded_instrument_icon,
    WritePaymentInstrumentCallback callback,
    blink::ServiceWorkerStatusCode status,
    scoped_refptr<ServiceWorkerRegistration> registration) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (status != blink::ServiceWorkerStatusCode::kOk) {
    std::move(callback).Run(PaymentHandlerStatus::NO_ACTIVE_WORKER);
    return;
  }

  StoredPaymentInstrumentProto instrument_proto;
  instrument_proto.set_registration_id(registration->id());
  instrument_proto.set_decoded_instrument_icon(decoded_instrument_icon);
  instrument_proto.set_instrument_key(instrument_key);
  instrument_proto.set_name(instrument->name);
  instrument_proto.set_method(instrument->method);
  for (const auto& icon : instrument->icons) {
    StoredPaymentInstrumentImageObject* image_object_proto =
        instrument_proto.add_icons();
    image_object_proto->set_src(icon.src.spec());
    image_object_proto->set_type(base::UTF16ToUTF8(icon.type));
    for (const auto& size : icon.sizes) {
      ImageSizeProto* size_proto = image_object_proto->add_sizes();
      size_proto->set_width(size.width());
      size_proto->set_height(size.height());
    }
  }

  std::string serialized_instrument;
  bool success = instrument_proto.SerializeToString(&serialized_instrument);
  DCHECK(success);

  StoredPaymentInstrumentKeyInfoProto key_info_proto;
  key_info_proto.set_key(instrument_key);
  key_info_proto.set_insertion_order(base::Time::Now().ToInternalValue());

  std::string serialized_key_info;
  success = key_info_proto.SerializeToString(&serialized_key_info);
  DCHECK(success);

  service_worker_context_->StoreRegistrationUserData(
      registration->id(), registration->key(),
      {{CreatePaymentInstrumentKey(instrument_key), serialized_instrument},
       {CreatePaymentInstrumentKeyInfoKey(instrument_key),
        serialized_key_info}},
      base::BindOnce(&PaymentAppDatabase::DidWritePaymentInstrument,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void PaymentAppDatabase::DidWritePaymentInstrument(
    WritePaymentInstrumentCallback callback,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  return std::move(callback).Run(
      status == blink::ServiceWorkerStatusCode::kOk
          ? PaymentHandlerStatus::SUCCESS
          : PaymentHandlerStatus::STORAGE_OPERATION_FAILED);
}

void PaymentAppDatabase::DidFindRegistrationToClearPaymentInstruments(
    const GURL& scope,
    ClearPaymentInstrumentsCallback callback,
    blink::ServiceWorkerStatusCode status,
    scoped_refptr<ServiceWorkerRegistration> registration) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (status != blink::ServiceWorkerStatusCode::kOk) {
    std::move(callback).Run(PaymentHandlerStatus::NO_ACTIVE_WORKER);
    return;
  }

  KeysOfPaymentInstruments(
      scope,
      base::BindOnce(&PaymentAppDatabase::DidGetKeysToClearPaymentInstruments,
                     weak_ptr_factory_.GetWeakPtr(), std::move(registration),
                     std::move(callback)));
}

void PaymentAppDatabase::DidGetKeysToClearPaymentInstruments(
    scoped_refptr<ServiceWorkerRegistration> registration,
    ClearPaymentInstrumentsCallback callback,
    const std::vector<std::string>& keys,
    PaymentHandlerStatus status) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (status != PaymentHandlerStatus::SUCCESS) {
    std::move(callback).Run(PaymentHandlerStatus::NOT_FOUND);
    return;
  }

  std::vector<std::string> keys_with_prefix;
  for (const auto& key : keys) {
    keys_with_prefix.push_back(CreatePaymentInstrumentKey(key));
    keys_with_prefix.push_back(CreatePaymentInstrumentKeyInfoKey(key));
  }

  // Clear payment app info after clearing all payment instruments.
  keys_with_prefix.push_back(CreatePaymentAppKey(registration->scope().spec()));

  service_worker_context_->ClearRegistrationUserData(
      registration->id(), keys_with_prefix,
      base::BindOnce(&PaymentAppDatabase::DidClearPaymentInstruments,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void PaymentAppDatabase::DidClearPaymentInstruments(
    ClearPaymentInstrumentsCallback callback,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  return std::move(callback).Run(status == blink::ServiceWorkerStatusCode::kOk
                                     ? PaymentHandlerStatus::SUCCESS
                                     : PaymentHandlerStatus::NOT_FOUND);
}

}  // namespace content
