// 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/gif/extractor.h"

#include <cstdint>
#include <optional>
#include <string>
#include <vector>

#include "absl/status/status.h"
#include "absl/status/status_matchers.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "formats/asset_box.h"
#include "formats/asset_byte_info.h"
#include "formats/byte_range.h"
#include "formats/extractor_result.h"
#include "formats/gif/constants.h"
#include "formats/gif/test_builder.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "riegeli/base/types.h"
#include "riegeli/bytes/reader.h"
#include "riegeli/bytes/string_reader.h"
#include "testing/jumbf_utils.h"

namespace credentio {
namespace {

using ::absl_testing::IsOkAndHolds;
using ::absl_testing::StatusIs;
using ::testing::HasSubstr;

class NoSizeStringReader : public riegeli::StringReader<> {
 public:
  using riegeli::StringReader<>::StringReader;
  bool SupportsSize() override { return false; }
};

class SizeNotValuedStringReader : public riegeli::StringReader<> {
 public:
  using riegeli::StringReader<>::StringReader;
  bool SupportsSize() override { return true; }

 protected:
  std::optional<riegeli::Position> SizeImpl() override { return std::nullopt; }
};

constexpr int64_t kMaxChunkBytes = 2 * 1048576;  // 2MiB

struct TestCase {
  std::string name;
  std::string contents;
  absl::StatusOr<ExtractorResult> result;
  uint32_t max_chunk_bytes = kMaxChunkBytes;
};

class ExtractorTest : public testing::TestWithParam<TestCase> {};

INSTANTIATE_TEST_SUITE_P(
    ExtractorTests, ExtractorTest,
    testing::ValuesIn({
        TestCase{
            .name = "Valid",
            .contents =
                []() {
                  TestGifBuilder builder;
                  builder.AddGifHeader();
                  builder.AddLogicalDescriptor(/*has_color_table=*/false);
                  builder.AddBlock(kGifExtensionIntroducer,
                                   kGifExtensionApplication,
                                   std::string(kGifC2paIdentifier) + "___",
                                   "manifest_store");
                  return builder.GetAsset();
                }(),
            .result =
                ExtractorResult{
                    .manifest_store = "manifest_store",
                    .asset_byte_info =
                        {
                            .manifest_store_location = ByteRange{.offset = 13,
                                                                 .length = 30},
                            .boxes = {AssetBox{.identifier = "GIF89a",
                                               .byte_range = {.offset = 0,
                                                              .length = 6}},
                                      AssetBox{.identifier = "LSD",
                                               .byte_range = {.offset = 6,
                                                              .length = 7}},
                                      AssetBox{.identifier = "C2PA",
                                               .byte_range = {.offset = 13,
                                                              .length = 30}}},
                        },
                },
        },
        TestCase{
            .name = "NoC2pa",
            .contents =
                []() {
                  TestGifBuilder builder;
                  builder.AddGifHeader();
                  builder.AddLogicalDescriptor(/*has_color_table=*/false);
                  return builder.GetAsset();
                }(),
            .result = absl::NotFoundError("No manifest store found"),
        },
        TestCase{
            .name = "MultipleC2pa",
            .contents =
                []() {
                  TestGifBuilder builder;
                  builder.AddGifHeader();
                  builder.AddLogicalDescriptor(/*has_color_table=*/false);
                  builder.AddBlock(
                      kGifExtensionIntroducer, kGifExtensionApplication,
                      std::string(kGifC2paIdentifier) + "___", "first_store");
                  builder.AddBlock(
                      kGifExtensionIntroducer, kGifExtensionApplication,
                      std::string(kGifC2paIdentifier) + "___", "second_store");
                  return builder.GetAsset();
                }(),
            .result = absl::NotFoundError("Multiple manifest stores found"),
        },
    }),
    [](const testing::TestParamInfo<ExtractorTest::ParamType>& info) {
      return info.param.name;
    });

TEST_P(ExtractorTest, Extract) {
  const TestCase& param = GetParam();
  const absl::StatusOr<ExtractorResult>& expected = param.result;
  riegeli::StringReader<> input(param.contents);
  absl::StatusOr<std::string> result =
      GifExtractor().ExtractManifestStore(input);

  if (expected.ok()) {
    EXPECT_THAT(result, IsOkAndHolds(expected->manifest_store));
  } else {
    EXPECT_THAT(result, StatusIs(expected.status().code(),
                                 HasSubstr(expected.status().message())));
  }
}

TEST_P(ExtractorTest, ExtractWorksWhenPrefixPadded) {
  const TestCase& param = GetParam();
  const absl::StatusOr<ExtractorResult>& expected = param.result;
  std::string contents = "padding" + param.contents;
  riegeli::StringReader<> input(contents);
  ASSERT_TRUE(input.Seek(7));
  absl::StatusOr<std::string> result =
      GifExtractor().ExtractManifestStore(input);

  if (expected.ok()) {
    EXPECT_THAT(result, IsOkAndHolds(expected->manifest_store));
  } else {
    EXPECT_THAT(result, StatusIs(expected.status().code(),
                                 HasSubstr(expected.status().message())));
  }
}

TEST_P(ExtractorTest, ExtractManifestStoreLocationWithSuffixPadded) {
  const TestCase& param = GetParam();
  const absl::StatusOr<ExtractorResult>& expected = param.result;
  std::string contents = param.contents + "padding";
  riegeli::StringReader<> input(contents);

  absl::StatusOr<std::optional<ByteRange>> result =
      GifExtractor().ExtractManifestStoreLocation(
          input, {.end_offset = static_cast<int64_t>(contents.size() - 7)});

  if (expected.ok()) {
    EXPECT_THAT(result, IsOkAndHolds(
                            expected->asset_byte_info.manifest_store_location));
  } else {
    EXPECT_THAT(result, StatusIs(expected.status().code(),
                                 HasSubstr(expected.status().message())));
  }
}

TEST_P(ExtractorTest, ExtractBoxesWithSuffixPadded) {
  const TestCase& param = GetParam();
  const absl::StatusOr<ExtractorResult>& expected = param.result;
  std::string contents = param.contents + "padding";
  riegeli::StringReader<> input(contents);

  absl::StatusOr<std::vector<AssetBox>> result = GifExtractor().ExtractBoxes(
      input, {.end_offset = static_cast<int64_t>(contents.size()) - 7});

  if (expected.ok()) {
    EXPECT_THAT(result, IsOkAndHolds(expected->asset_byte_info.boxes));
  } else {
    EXPECT_THAT(result, StatusIs(expected.status().code(),
                                 HasSubstr(expected.status().message())));
  }
}

TEST_P(ExtractorTest, ExtractManifestStoreLocationRequiresC2pa) {
  const TestCase& param = GetParam();
  const absl::StatusOr<ExtractorResult>& expected = param.result;
  riegeli::StringReader<> input(param.contents);
  absl::StatusOr<std::optional<ByteRange>> result =
      GifExtractor().ExtractManifestStoreLocation(input, {});

  if (expected.ok()) {
    EXPECT_THAT(result, IsOkAndHolds(
                            expected->asset_byte_info.manifest_store_location));
  } else {
    EXPECT_THAT(result, StatusIs(expected.status().code(),
                                 HasSubstr(expected.status().message())));
  }
}

TEST_P(ExtractorTest, ExtractManifestStoreLocationDoesNotRequireC2pa) {
  const TestCase& param = GetParam();
  const absl::StatusOr<ExtractorResult>& expected = param.result;
  riegeli::StringReader<> input(param.contents);
  absl::StatusOr<std::optional<ByteRange>> result =
      GifExtractor().ExtractManifestStoreLocation(input,
                                                  {.requires_c2pa = false});

  if (expected.ok()) {
    EXPECT_THAT(result, IsOkAndHolds(
                            expected->asset_byte_info.manifest_store_location));
  } else if (expected.status().code() == absl::StatusCode::kNotFound &&
             expected.status().message() != "Multiple manifest stores found") {
    EXPECT_THAT(result, IsOkAndHolds(std::nullopt));
  } else {
    EXPECT_THAT(result, StatusIs(expected.status().code(),
                                 HasSubstr(expected.status().message())));
  }
}

TEST_P(ExtractorTest, ExtractBoxes) {
  const TestCase& param = GetParam();
  const absl::StatusOr<ExtractorResult>& expected = param.result;
  riegeli::StringReader<> input(param.contents);
  absl::StatusOr<std::vector<AssetBox>> result =
      GifExtractor().ExtractBoxes(input, {});

  if (expected.ok()) {
    EXPECT_THAT(result, IsOkAndHolds(expected->asset_byte_info.boxes));
  } else {
    EXPECT_THAT(result, StatusIs(expected.status().code(),
                                 HasSubstr(expected.status().message())));
  }
}

TEST(GifExtractorTest, FailsWhenSizeNotSupported) {
  std::string contents = "test";
  NoSizeStringReader input(contents);

  GifExtractor extractor;
  EXPECT_THAT(extractor.ExtractBoxes(input, {}),
              StatusIs(absl::StatusCode::kInvalidArgument,
                       HasSubstr("Input does not support size")));
}

TEST(GifExtractorTest, FailsWhenSizeHasNoValue) {
  std::string contents = "test";
  SizeNotValuedStringReader input(contents);

  GifExtractor extractor;
  EXPECT_THAT(extractor.ExtractBoxes(input, {}),
              StatusIs(absl::StatusCode::kInvalidArgument,
                       HasSubstr("Input does not support size")));
}

TEST(GifExtractorTest,
     ExtractManifestStoreLocationStopsWhenBlockExceedsEndOffset) {
  TestGifBuilder builder;
  builder.AddGifHeader();
  builder.AddLogicalDescriptor(/*has_color_table=*/false);
  builder.AddBlock(kGifExtensionIntroducer, kGifExtensionApplication,
                   std::string(kGifC2paIdentifier) + "___", "manifest_store");
  std::string contents = builder.GetAsset();

  riegeli::StringReader<> input(contents);

  // LSD is at [6, 13). Set end_offset to 10.
  // It should stop at LSD and return NotFoundError because C2PA (at 13) is not
  // reached.
  absl::StatusOr<std::optional<ByteRange>> result =
      GifExtractor().ExtractManifestStoreLocation(input, {.end_offset = 10});

  EXPECT_THAT(result, StatusIs(absl::StatusCode::kNotFound,
                               HasSubstr("No manifest store found")));
}

TEST(GifExtractorTest, ExtractBoxesFailsWhenBlockExceedsEndOffset) {
  TestGifBuilder builder;
  builder.AddGifHeader();
  builder.AddLogicalDescriptor(/*has_color_table=*/false);
  std::string contents = builder.GetAsset();

  riegeli::StringReader<> input(contents);

  // LSD is at [6, 13). Set end_offset to 10.
  // It should fail with InvalidArgumentError because LSD extends past 10.
  absl::StatusOr<std::vector<AssetBox>> result =
      GifExtractor().ExtractBoxes(input, {.end_offset = 10});

  EXPECT_THAT(
      result,
      StatusIs(absl::StatusCode::kInvalidArgument,
               HasSubstr("Block extends past the declared end of the input")));
}

TEST(GifExtractorTest,
     ExtractManifestStoreLocationIgnoresC2paAfterImageDescriptor) {
  TestGifBuilder builder;
  builder.AddGifHeader();
  builder.AddLogicalDescriptor(/*has_color_table=*/false);
  builder.AddImageDescriptor(/*has_color_table=*/false);
  builder.AddBlock(kGifExtensionIntroducer, kGifExtensionApplication,
                   std::string(kGifC2paIdentifier) + "___", "manifest_store");
  std::string contents = builder.GetAsset();

  riegeli::StringReader<> input(contents);

  // It should stop at the image descriptor and not find the C2PA block.
  absl::StatusOr<std::optional<ByteRange>> result =
      GifExtractor().ExtractManifestStoreLocation(input, {});

  EXPECT_THAT(result, StatusIs(absl::StatusCode::kNotFound,
                               HasSubstr("No manifest store found")));
}

class FakeGifExtractor : public GifExtractor {
 public:
  absl::StatusOr<std::optional<ByteRange>> ExtractManifestStoreLocation(
      riegeli::Reader& input, ExtractOptions options) const override {
    if (fake_location_.has_value()) {
      return fake_location_;
    }
    return GifExtractor::ExtractManifestStoreLocation(input, options);
  }
  void SetFakeLocation(ByteRange loc) { fake_location_ = loc; }

 private:
  mutable std::optional<ByteRange> fake_location_;
};

TEST(GifExtractorTest, ExtractManifestStoreFailsOnMalformedC2paData) {
  std::string contents;
  contents.resize(14, 'A');  // 14 bytes of padding
  contents += '\005';        // block size 5
  contents += "abc";         // but only 3 bytes

  riegeli::StringReader<> input(contents);

  FakeGifExtractor extractor;
  extractor.SetFakeLocation(ByteRange{.offset = 0, .length = 18});

  absl::StatusOr<std::string> result = extractor.ExtractManifestStore(input);

  EXPECT_THAT(result,
              StatusIs(absl::StatusCode::kInvalidArgument,
                       HasSubstr("Invalid block size in GIF C2PA data")));
}

TEST(GifExtractorTest, ExtractManifestStoreFailsOnOversizedData) {
  std::string contents(10, 'A');
  riegeli::StringReader<> input(contents);

  FakeGifExtractor extractor;
  extractor.SetFakeLocation(
      ByteRange{.offset = 0, .length = 11 * 1024 * 1024 + 14});

  absl::StatusOr<std::string> result = extractor.ExtractManifestStore(input);

  EXPECT_THAT(result, StatusIs(absl::StatusCode::kInvalidArgument,
                               HasSubstr("Manifest store is too large")));
}

TEST(GifExtractorTest, MightBeC2paManifestStore) {
  EXPECT_TRUE(GifExtractor().MightBeC2paManifestStore(
      CreateStartOfManifestStorePayload()));
  EXPECT_FALSE(GifExtractor().MightBeC2paManifestStore("not a manifest store"));
}

}  // namespace
}  // namespace credentio
