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

#include "components/autofill/core/browser/payments/payments_network_interface.h"

#include <stdint.h>

#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/memory/scoped_refptr.h"
#include "base/time/time.h"
#include "base/values.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/data_model/addresses/autofill_profile.h"
#include "components/autofill/core/browser/metrics/payments/credit_card_save_metrics.h"
#include "components/autofill/core/browser/payments/account_info_getter.h"
#include "components/autofill/core/browser/payments/client_behavior_constants.h"
#include "components/autofill/core/browser/payments/legal_message_line.h"
#include "components/autofill/core/browser/payments/payments_autofill_client.h"
#include "components/autofill/core/browser/payments/payments_network_interface_base.h"
#include "components/autofill/core/browser/payments/payments_request_details.h"
#include "components/autofill/core/browser/payments/payments_requests/create_bnpl_payment_instrument_request.h"
#include "components/autofill/core/browser/payments/payments_requests/get_bnpl_payment_instrument_for_fetching_url_request.h"
#include "components/autofill/core/browser/payments/payments_requests/get_bnpl_payment_instrument_for_fetching_vcn_request.h"
#include "components/autofill/core/browser/payments/payments_requests/get_card_upload_details_request.h"
#include "components/autofill/core/browser/payments/payments_requests/get_details_for_create_bnpl_payment_instrument_request.h"
#include "components/autofill/core/browser/payments/payments_requests/get_details_for_enrollment_request.h"
#include "components/autofill/core/browser/payments/payments_requests/get_details_for_update_bnpl_payment_instrument_request.h"
#include "components/autofill/core/browser/payments/payments_requests/get_iban_upload_details_request.h"
#include "components/autofill/core/browser/payments/payments_requests/get_unmask_details_request.h"
#include "components/autofill/core/browser/payments/payments_requests/get_wallet_reminder_notice_request.h"
#include "components/autofill/core/browser/payments/payments_requests/opt_change_request.h"
#include "components/autofill/core/browser/payments/payments_requests/record_legal_reminder_acknowledgment_request.h"
#include "components/autofill/core/browser/payments/payments_requests/select_challenge_option_request.h"
#include "components/autofill/core/browser/payments/payments_requests/unmask_card_request.h"
#include "components/autofill/core/browser/payments/payments_requests/unmask_iban_request.h"
#include "components/autofill/core/browser/payments/payments_requests/update_bnpl_payment_instrument_request.h"
#include "components/autofill/core/browser/payments/payments_requests/update_virtual_card_enrollment_request.h"
#include "components/autofill/core/browser/payments/payments_requests/upload_card_request.h"
#include "components/autofill/core/browser/payments/payments_requests/upload_iban_request.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"

namespace autofill::payments {
namespace {

using PaymentsRpcResult = PaymentsAutofillClient::PaymentsRpcResult;

}  // namespace

PaymentsNetworkInterface::PaymentsNetworkInterface(
    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
    signin::IdentityManager* identity_manager,
    AccountInfoGetter* account_info_getter,
    bool is_off_the_record)
    : PaymentsNetworkInterfaceBase(url_loader_factory,
                                   identity_manager,
                                   account_info_getter,
                                   is_off_the_record) {}

PaymentsNetworkInterface::~PaymentsNetworkInterface() = default;

void PaymentsNetworkInterface::Prepare() {
  if (access_token_.empty()) {
    StartTokenFetch(false);
  }
}

void PaymentsNetworkInterface::GetUnmaskDetails(
    base::OnceCallback<void(PaymentsRpcResult, UnmaskDetails&)> callback,
    const std::string& app_locale) {
  IssueRequest(std::make_unique<GetUnmaskDetailsRequest>(
      std::move(callback), app_locale,
      account_info_getter_->IsSyncFeatureEnabledForPaymentsServerMetrics()));
}

void PaymentsNetworkInterface::UnmaskCard(
    const UnmaskRequestDetails& request_details,
    base::OnceCallback<void(PaymentsRpcResult, const UnmaskResponseDetails&)>
        callback) {
  IssueRequest(std::make_unique<UnmaskCardRequest>(
      request_details,
      account_info_getter_->IsSyncFeatureEnabledForPaymentsServerMetrics(),
      std::move(callback)));
}

void PaymentsNetworkInterface::UnmaskIban(
    const UnmaskIbanRequestDetails& request_details,
    base::OnceCallback<void(PaymentsRpcResult, const std::u16string&)>
        callback) {
  IssueRequest(std::make_unique<UnmaskIbanRequest>(
      request_details,
      account_info_getter_->IsSyncFeatureEnabledForPaymentsServerMetrics(),
      std::move(callback)));
}

void PaymentsNetworkInterface::OptChange(
    const OptChangeRequestDetails request_details,
    base::OnceCallback<void(PaymentsRpcResult, OptChangeResponseDetails&)>
        callback) {
  IssueRequest(std::make_unique<OptChangeRequest>(
      request_details, std::move(callback),
      account_info_getter_->IsSyncFeatureEnabledForPaymentsServerMetrics()));
}

void PaymentsNetworkInterface::GetCardUploadDetails(
    const std::vector<AutofillProfile>& addresses,
    const int detected_values,
    const std::vector<ClientBehaviorConstants>& client_behavior_signals,
    const std::string& app_locale,
    GetCardUploadDetailsCallback callback,
    const int billable_service_number,
    const int64_t billing_customer_number,
    UploadCardSource upload_card_source) {
  base::TimeTicks start_time = base::TimeTicks::Now();
  GetCardUploadDetailsCallback callback_with_latency_metrics = base::BindOnce(
      [](GetCardUploadDetailsCallback callback, base::TimeTicks start_time,
         PaymentsRpcResult result, const std::u16string& context_token,
         std::unique_ptr<base::DictValue> legal_message,
         std::vector<std::pair<int, int>> supported_card_bin_ranges) {
        autofill_metrics::LogGetCardUploadDetailsRequestLatencyMetric(
            base::TimeTicks::Now() - start_time,
            result == PaymentsRpcResult::kSuccess);
        std::move(callback).Run(std::move(result), context_token,
                                std::move(legal_message),
                                std::move(supported_card_bin_ranges));
      },
      std::move(callback), start_time);

  IssueRequest(std::make_unique<GetCardUploadDetailsRequest>(
      addresses, detected_values, client_behavior_signals,
      account_info_getter_->IsSyncFeatureEnabledForPaymentsServerMetrics(),
      app_locale, std::move(callback_with_latency_metrics),
      billable_service_number, billing_customer_number, upload_card_source));
}

void PaymentsNetworkInterface::UploadCard(
    const UploadCardRequestDetails& request_details,
    base::OnceCallback<void(PaymentsRpcResult,
                            const UploadCardResponseDetails&)> callback) {
  IssueRequest(std::make_unique<UploadCardRequest>(
      request_details,
      account_info_getter_->IsSyncFeatureEnabledForPaymentsServerMetrics(),
      std::move(callback)));
}

void PaymentsNetworkInterface::GetIbanUploadDetails(
    const std::string& app_locale,
    const std::vector<ClientBehaviorConstants>& client_behavior_signals,
    int64_t billing_customer_number,
    const std::string& country_code,
    base::OnceCallback<void(PaymentsRpcResult,
                            const std::u16string& validation_regex,
                            const std::u16string& context_token,
                            std::unique_ptr<base::DictValue>)> callback) {
  IssueRequest(std::make_unique<GetIbanUploadDetailsRequest>(
      account_info_getter_->IsSyncFeatureEnabledForPaymentsServerMetrics(),
      app_locale, client_behavior_signals, billing_customer_number,
      country_code, std::move(callback)));
}

void PaymentsNetworkInterface::UploadIban(
    const UploadIbanRequestDetails& details,
    base::OnceCallback<void(PaymentsRpcResult)> callback) {
  IssueRequest(std::make_unique<UploadIbanRequest>(
      details,
      account_info_getter_->IsSyncFeatureEnabledForPaymentsServerMetrics(),
      std::move(callback)));
}

void PaymentsNetworkInterface::SelectChallengeOption(
    const SelectChallengeOptionRequestDetails& request_details,
    base::OnceCallback<void(PaymentsRpcResult, const std::string&)> callback) {
  IssueRequest(std::make_unique<SelectChallengeOptionRequest>(
      request_details, std::move(callback)));
}

void PaymentsNetworkInterface::GetVirtualCardEnrollmentDetails(
    const GetDetailsForEnrollmentRequestDetails& request_details,
    base::OnceCallback<void(PaymentsRpcResult,
                            const GetDetailsForEnrollmentResponseDetails&)>
        callback) {
  IssueRequest(std::make_unique<GetDetailsForEnrollmentRequest>(
      request_details, std::move(callback)));
}

void PaymentsNetworkInterface::UpdateVirtualCardEnrollment(
    const UpdateVirtualCardEnrollmentRequestDetails& request_details,
    base::OnceCallback<void(PaymentsRpcResult)> callback) {
  IssueRequest(std::make_unique<UpdateVirtualCardEnrollmentRequest>(
      request_details, std::move(callback)));
}

void PaymentsNetworkInterface::GetDetailsForCreateBnplPaymentInstrument(
    const GetDetailsForCreateBnplPaymentInstrumentRequestDetails&
        request_details,
    base::OnceCallback<void(PaymentsRpcResult,
                            std::string context_token,
                            LegalMessageLines)> callback) {
  IssueRequest(
      std::make_unique<GetDetailsForCreateBnplPaymentInstrumentRequest>(
          request_details,
          /*full_sync_enabled=*/
          account_info_getter_->IsSyncFeatureEnabledForPaymentsServerMetrics(),
          std::move(callback)));
}

void PaymentsNetworkInterface::CreateBnplPaymentInstrument(
    const CreateBnplPaymentInstrumentRequestDetails& request_details,
    base::OnceCallback<void(PaymentsRpcResult, std::string instrument_id)>
        callback) {
  IssueRequest(std::make_unique<CreateBnplPaymentInstrumentRequest>(
      request_details,
      /*full_sync_enabled=*/
      account_info_getter_->IsSyncFeatureEnabledForPaymentsServerMetrics(),
      std::move(callback)));
}

void PaymentsNetworkInterface::GetBnplPaymentInstrumentForFetchingVcn(
    GetBnplPaymentInstrumentForFetchingVcnRequestDetails request_details,
    base::OnceCallback<void(PaymentsRpcResult,
                            const BnplFetchVcnResponseDetails&)> callback) {
  IssueRequest(std::make_unique<GetBnplPaymentInstrumentForFetchingVcnRequest>(
      request_details,
      /*full_sync_enabled=*/
      account_info_getter_->IsSyncFeatureEnabledForPaymentsServerMetrics(),
      std::move(callback)));
}

void PaymentsNetworkInterface::GetBnplPaymentInstrumentForFetchingUrl(
    GetBnplPaymentInstrumentForFetchingUrlRequestDetails request_details,
    base::OnceCallback<void(PaymentsRpcResult,
                            const BnplFetchUrlResponseDetails&)> callback) {
  IssueRequest(std::make_unique<GetBnplPaymentInstrumentForFetchingUrlRequest>(
      request_details,
      /*full_sync_enabled=*/
      account_info_getter_->IsSyncFeatureEnabledForPaymentsServerMetrics(),
      std::move(callback)));
}

void PaymentsNetworkInterface::GetDetailsForUpdateBnplPaymentInstrument(
    const GetDetailsForUpdateBnplPaymentInstrumentRequestDetails&
        request_details,
    base::OnceCallback<void(PaymentsRpcResult,
                            std::string context_token,
                            LegalMessageLines)> callback) {
  IssueRequest(
      std::make_unique<GetDetailsForUpdateBnplPaymentInstrumentRequest>(
          request_details,
          /*full_sync_enabled=*/
          account_info_getter_->IsSyncFeatureEnabledForPaymentsServerMetrics(),
          std::move(callback)));
}

void PaymentsNetworkInterface::UpdateBnplPaymentInstrument(
    const UpdateBnplPaymentInstrumentRequestDetails& request_details,
    base::OnceCallback<void(PaymentsRpcResult)> callback) {
  IssueRequest(std::make_unique<UpdateBnplPaymentInstrumentRequest>(
      request_details,
      /*full_sync_enabled=*/
      account_info_getter_->IsSyncFeatureEnabledForPaymentsServerMetrics(),
      std::move(callback)));
}

void PaymentsNetworkInterface::GetWalletReminderNotice(
    const GetWalletReminderNoticeRequestDetails& request_details,
    base::OnceCallback<void(PaymentsRpcResult,
                            const GetWalletReminderNoticeResponseDetails&)>
        callback) {
  IssueRequest(std::make_unique<GetWalletReminderNoticeRequest>(
      request_details, std::move(callback)));
}

void PaymentsNetworkInterface::RecordLegalReminderAcknowledgment(
    const RecordLegalReminderAcknowledgmentRequestDetails& request_details,
    base::OnceCallback<void(PaymentsRpcResult)> callback) {
  IssueRequest(std::make_unique<RecordLegalReminderAcknowledgmentRequest>(
      request_details, std::move(callback)));
}

}  // namespace autofill::payments
