// 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/tiff/assessor.h"

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

#include "absl/status/status.h"
#include "absl/status/status_matchers.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "riegeli/bytes/string_reader.h"

namespace credentio {
namespace {

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

TEST(IsAssetSupportedTest, ErrorTooFewBytes) {
  std::string image = "\xab";
  riegeli::StringReader<> input(image);
  EXPECT_THAT(
      TiffAssessor().IsSupported(input),
      StatusIs(absl::StatusCode::kDataLoss, HasSubstr("kUnexpectedEof")));
}

TEST(IsAssetSupportedTest, FalseForInvalidBeginning) {
  std::string image = "this_is_not_a_riff";
  riegeli::StringReader<> input(image);
  EXPECT_THAT(TiffAssessor().IsSupported(input), IsOkAndHolds(false));
}

TEST(IsAssetSupportedTest, ValidStartingBigEndianBytes) {
  std::vector<uint8_t> data = {0x4d, 0x4d, 0x00, 0x2a};
  std::string image = std::string(data.begin(), data.end());
  riegeli::StringReader<> input(image);
  EXPECT_THAT(TiffAssessor().IsSupported(input), IsOkAndHolds(true));
}

TEST(IsAssetSupportedTest, ValidStartingLittleEndianBytes) {
  std::vector<uint8_t> data = {0x49, 0x49, 0x2a, 0x00};
  std::string image = std::string(data.begin(), data.end());
  riegeli::StringReader<> input(image);
  EXPECT_THAT(TiffAssessor().IsSupported(input), IsOkAndHolds(true));
}

TEST(IsAssetSupportedTest, ValidStartingBigEndianBytesAtOffset2) {
  std::vector<uint8_t> data = {'a', 'b', 0x4d, 0x4d, 0x00, 0x2a};
  std::string image = std::string(data.begin(), data.end());
  riegeli::StringReader<> input(image);

  // Invalid at 0
  EXPECT_THAT(TiffAssessor().IsSupported(input), IsOkAndHolds(false));
  EXPECT_EQ(input.pos(), 0);

  // Valid at 2
  ASSERT_TRUE(input.Seek(2));
  EXPECT_THAT(TiffAssessor().IsSupported(input), IsOkAndHolds(true));
  EXPECT_EQ(input.pos(), 2);
}

TEST(IsAssetSupportedTest, ValidStartingLittleEndianBytesAtOffset2) {
  std::vector<uint8_t> data = {'a', 'b', 0x49, 0x49, 0x2a, 0x00};
  std::string image = std::string(data.begin(), data.end());
  riegeli::StringReader<> input(image);

  // Invalid at 0
  EXPECT_THAT(TiffAssessor().IsSupported(input), IsOkAndHolds(false));
  EXPECT_EQ(input.pos(), 0);

  // Valid at 2
  ASSERT_TRUE(input.Seek(2));
  EXPECT_THAT(TiffAssessor().IsSupported(input), IsOkAndHolds(true));
  EXPECT_EQ(input.pos(), 2);
}

}  // namespace
}  // namespace credentio
