// 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 "formats/pdf/manifest_store_merger.h"

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

#include "absl/log/absl_check.h"
#include "absl/status/status.h"
#include "absl/status/status_matchers.h"
#include "absl/status/statusor.h"
#include "absl/strings/cord.h"
#include "absl/strings/string_view.h"
#include "constants/labels.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "jumbf/box.h"
#include "jumbf/box_builder.h"
#include "jumbf/constants.h"
#include "jumbf/encode_params.h"
#include "jumbf/parse.h"
#include "uuid/uuid.h"

namespace credentio {
namespace {

using ::absl_testing::IsOkAndHolds;
using ::absl_testing::StatusIs;
using ::credentio::kManifestStoreLabel;
using ::credentio::kManifestStoreUuid;
using ::credentio::kStandardManifestUuid;
using ::jumbf::DescriptionBoxOptions;
using ::jumbf::kCborBoxType;
using ::jumbf::SuperBox;
using ::jumbf::SuperBoxBuilder;

std::string CreateTestManifestStore(absl::string_view manifest_label,
                                    absl::string_view payload_data) {
  SuperBoxBuilder manifest_builder(
      kStandardManifestUuid,
      DescriptionBoxOptions{.requestable_iff_label = true,
                            .label = absl::Cord(manifest_label)});
  ABSL_CHECK_OK(
      manifest_builder.AddContent(kCborBoxType, absl::Cord(payload_data)));
  absl::StatusOr<jumbf::BuiltSuperBox> manifest_box =
      std::move(manifest_builder).Finalize();
  ABSL_CHECK_OK(manifest_box);

  SuperBoxBuilder store_builder(
      kManifestStoreUuid,
      DescriptionBoxOptions{.requestable_iff_label = true,
                            .label = absl::Cord(kManifestStoreLabel)});
  ABSL_CHECK_OK(store_builder.AddChild(*std::move(manifest_box)));
  absl::StatusOr<jumbf::BuiltSuperBox> store_box =
      std::move(store_builder).Finalize();
  ABSL_CHECK_OK(store_box);
  return std::string(std::move(*store_box).AsCord());
}

TEST(ManifestStoreMergerTest, EmptyStoresListReturnsError) {
  EXPECT_THAT(MergeManifestStores({}),
              StatusIs(absl::StatusCode::kInvalidArgument));
}

TEST(ManifestStoreMergerTest, SingleStoreReturnedUnmodified) {
  std::string store = CreateTestManifestStore("test_manifest", "data");
  EXPECT_THAT(MergeManifestStores({store}), IsOkAndHolds(store));
}

TEST(ManifestStoreMergerTest, MultipleStoresMergedInCorrectOrder) {
  std::string store1 = CreateTestManifestStore("manifest_1", "data_1");
  std::string store2 = CreateTestManifestStore("manifest_2", "data_2");

  absl::StatusOr<std::string> merged = MergeManifestStores({store1, store2});
  ABSL_ASSERT_OK(merged);

  absl::string_view view = *merged;
  absl::StatusOr<SuperBox> superbox =
      jumbf::ConsumeSuperBox(&view, /*recursion_limit=*/9);
  ABSL_ASSERT_OK(superbox);

  EXPECT_TRUE(view.empty());  // Entire buffer consumed.
  EXPECT_EQ(superbox->description.type_uuid, kManifestStoreUuid);
  ASSERT_EQ(superbox->contents.size(), 2);

  // Active manifest from store2 should be placed LAST in contents.
  const auto& box2 = superbox->contents.back();
  EXPECT_TRUE(box2.Holds<SuperBox>());
  EXPECT_EQ(box2.Get<SuperBox>().description.type_uuid, kStandardManifestUuid);
  EXPECT_EQ(box2.Get<SuperBox>().description.label, "manifest_2");

  // Initial manifest from store1 should be placed FIRST in contents.
  const auto& box1 = superbox->contents.front();
  EXPECT_TRUE(box1.Holds<SuperBox>());
  EXPECT_EQ(box1.Get<SuperBox>().description.type_uuid, kStandardManifestUuid);
  EXPECT_EQ(box1.Get<SuperBox>().description.label, "manifest_1");
}

TEST(ManifestStoreMergerTest, MalformedStoreReturnsError) {
  std::string valid_store = CreateTestManifestStore("manifest_1", "data_1");
  std::string malformed_store = "not a jumbf box";

  EXPECT_FALSE(MergeManifestStores({valid_store, malformed_store}).ok());
}

}  // namespace
}  // namespace credentio
