// 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 "content/browser/devtools/protocol/digital_credentials_handler.h"

#include "base/check.h"
#include "base/json/json_reader.h"
#include "base/values.h"
#include "content/browser/devtools/protocol/handler_helpers.h"
#include "content/browser/digital_credentials/digital_credential_environment.h"
#include "content/browser/digital_credentials/virtual_wallet.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/public/browser/digital_identity_provider.h"

namespace content::protocol {

DigitalCredentialsHandler::DigitalCredentialsHandler()
    : DevToolsDomainHandler(DigitalCredentials::Metainfo::domainName) {}

DigitalCredentialsHandler::~DigitalCredentialsHandler() = default;

void DigitalCredentialsHandler::SetRenderer(int process_host_id,
                                            RenderFrameHostImpl* frame_host) {
  frame_host_ = frame_host;
}

void DigitalCredentialsHandler::Wire(UberDispatcher* dispatcher) {
  DigitalCredentials::Dispatcher::wire(dispatcher, this);
}

DispatchResponse DigitalCredentialsHandler::SetVirtualWalletBehavior(
    const String& in_action,
    std::optional<String> in_protocol,
    std::unique_ptr<protocol::DictionaryValue> in_response,
    std::optional<String> in_frame_id) {
  if (!frame_host_) {
    return DispatchResponse::InvalidParams(
        "Command must be issued on a session attached to a frame");
  }

  if (in_action != DigitalCredentials::VirtualWalletActionEnum::Respond &&
      (in_protocol || in_response)) {
    return DispatchResponse::InvalidParams(
        "Protocol and response are only allowed when action is 'respond'");
  }

  FrameTreeNode* target_node = frame_host_->frame_tree_node();
  if (in_frame_id.has_value()) {
    target_node = FrameTreeNodeFromDevToolsFrameToken(
        frame_host_->frame_tree_node(), *in_frame_id);
    if (!target_node) {
      return DispatchResponse::InvalidParams(
          "No frame found with the given frameId");
    }
  }

  VirtualWallet* wallet =
      DigitalCredentialEnvironment::GetInstance()->GetOrCreateVirtualWallet(
          target_node);
  CHECK(wallet);

  if (in_action == DigitalCredentials::VirtualWalletActionEnum::Clear) {
    wallet->Clear();
    return DispatchResponse::Success();
  }

  if (in_action == DigitalCredentials::VirtualWalletActionEnum::Respond) {
    if (!in_protocol || !in_response) {
      return DispatchResponse::InvalidParams(
          "Protocol and response required for 'respond' action");
    }

    wallet->set_action(VirtualWallet::Action::kRespond);
    DigitalIdentityProvider::DigitalCredential credential(
        *in_protocol, base::Value(std::move(*in_response)));
    wallet->SetCredential(std::move(credential));
    return DispatchResponse::Success();
  }

  if (in_action == DigitalCredentials::VirtualWalletActionEnum::Decline) {
    wallet->set_action(VirtualWallet::Action::kDecline);
    return DispatchResponse::Success();
  }

  if (in_action == DigitalCredentials::VirtualWalletActionEnum::Wait) {
    wallet->set_action(VirtualWallet::Action::kWait);
    return DispatchResponse::Success();
  }

  return DispatchResponse::InvalidParams("Unknown action");
}

}  // namespace content::protocol
