// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "utils/crjson_utils.h"

#include <cstdint>
#include <string>

#include "absl/functional/function_ref.h"
#include "absl/strings/escaping.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "cbor/cbor.h"
#include "cppbor/cppbor.h"
#include "nlohmann/json.hpp"

namespace credentio {

using Json = ::nlohmann::json;

bool RecordString(const cbor::MapView& map, absl::string_view key,
                  bool required, Json& json) {
  if (auto val = map.GetOptionalString(key); val.has_value()) {
    json[key] = *val;
    return true;
  }
  if (required) {
    json["_missing"].push_back(key);
  }
  return false;
}

bool RecordByteString(const cbor::MapView& map, absl::string_view key,
                      bool required, Json& json) {
  if (auto val = map.GetOptionalByteString(key); val.has_value()) {
    json[key] = absl::StrCat("b64'", absl::Base64Escape(*val), "'");
    return true;
  }
  if (required) {
    json["_missing"].push_back(key);
  }
  return false;
}

bool RecordByteString(const cbor::MapView& map, uint32_t key, bool required,
                      Json& json) {
  if (auto val = map.GetByteString(key); val.ok()) {
    json[std::to_string(key)] =
        absl::StrCat("b64'", absl::Base64Escape(*val), "'");
    return true;
  }
  if (required) {
    json["_missing"].push_back(std::to_string(key));
  }
  return false;
}

bool RecordUint64(const cbor::MapView& map, absl::string_view key,
                  bool required, Json& json) {
  if (auto val = map.GetOptionalUint64(key); val.has_value()) {
    json[key] = *val;
    return true;
  }
  if (required) {
    json["_missing"].push_back(key);
  }
  return false;
}

bool RecordInt64(const cbor::MapView& map, absl::string_view key, bool required,
                 Json& json) {
  if (auto val = map.GetOptionalInt64(key); val.has_value()) {
    json[key] = *val;
    return true;
  }
  if (required) {
    json["_missing"].push_back(key);
  }
  return false;
}

bool RecordBool(const cbor::MapView& map, absl::string_view key, bool required,
                Json& json) {
  if (auto val = map.GetOptionalBool(key); val.has_value()) {
    json[key] = *val;
    return true;
  }
  if (required) {
    json["_missing"].push_back(key);
  }
  return false;
}

bool RecordArray(const cbor::MapView& map, absl::string_view key, bool required,
                 ArrayProcessor processor, Json& json) {
  if (auto val = map.GetOptionalArray(key); val.has_value()) {
    json[key] = Json::array();
    for (int i = 0; i < val->size(); ++i) {
      auto elem = val->Get(i);
      if (!elem.ok()) {
        json[key].push_back(Json({{"_error", elem.status().message()}}));
        continue;
      }
      json[key].push_back(processor(i, *elem));
    }
    return true;
  }
  if (required) {
    json[key] = Json::array();
  }
  return false;
}

bool RecordArrayOfMaps(const cbor::MapView& map, absl::string_view key,
                       bool required, MapProcessor processor, Json& json) {
  if (auto val = map.GetOptionalArray(key); val.has_value()) {
    json[key] = Json::array();
    for (int i = 0; i < val->size(); ++i) {
      auto elem = val->Get(i);
      if (!elem.ok()) {
        json[key].push_back(Json({{"_error", elem.status().message()}}));
        continue;
      }
      auto map = elem->GetMap();
      if (!map.ok()) {
        json[key].push_back(Json({{"_error", elem.status().message()}}));
        continue;
      }
      json[key].push_back(processor(*map));
    }
    return true;
  }
  if (required) {
    json[key] = Json::array();
  }
  return false;
}

bool RecordMap(const cbor::MapView& map, absl::string_view key, bool required,
               MapProcessor processor, Json& json) {
  if (auto val = map.GetOptionalMap(key); val.has_value()) {
    json[key] = processor(*val);
    return true;
  }
  if (required) {
    cppbor::Map map;
    cbor::MapView map_view(&map);
    json[key] = processor(map_view);
  }
  return false;
}

}  // namespace credentio
