// 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/id3/writer.h"

#include <memory>
#include <string>
#include <utility>

#include "absl/functional/any_invocable.h"
#include "absl/log/absl_check.h"
#include "absl/status/status.h"
#include "absl/status/status_matchers.h"
#include "async/async_context.h"
#include "formats/byte_range.h"
#include "formats/id3/extractor.h"
#include "generator/generator.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "proto/generator.pb.h"
#include "proto/manifest.pb.h"
#include "proto/validation_status.pb.h"
#include "riegeli/bytes/string_reader.h"
#include "riegeli/bytes/string_writer.h"
#include "testing/nonprod_generator.h"
#include "testing/nonprod_validator.h"
#include "validator/asset_validator.h"

namespace credentio {
namespace {

using ::absl_testing::IsOkAndHolds;
using ::absl_testing::StatusIs;
using ::testing::AllOf;
using ::testing::Field;
using ::testing::Gt;
using ::testing::HasSubstr;
using ::testing::IsEmpty;
using ::testing::Optional;

constexpr char kMp3FileWithNoId3Tag[] = {'\xFF', '\xF3', '\x40', '\xC0',
                                         0x01,   0x02,   0x03,   0x04};

class Id3WriterTest : public ::testing::Test {
 protected:
  void SetUp() override {
    auto generator = CreateNonProdManifestStoreGenerator({});
    ABSL_CHECK_OK(generator);
    generator_ = std::move(*generator);
    writer_ = std::make_unique<Id3Writer>(generator_.get());
    auto validator = CreateNonProdValidator({});
    ABSL_CHECK_OK(validator);
    validator_ = std::move(*validator);
  }
  std::unique_ptr<ManifestStoreGenerator> generator_;
  std::unique_ptr<Id3Writer> writer_;
  std::unique_ptr<AssetValidator> validator_;
};

TEST_F(Id3WriterTest, Write) {
  std::string mp3_file_contents =
      std::string(kMp3FileWithNoId3Tag, sizeof(kMp3FileWithNoId3Tag));
  riegeli::StringReader source(mp3_file_contents);
  ABSL_ASSERT_OK(source.status());
  std::string result;
  riegeli::StringWriter destination(&result);
  ABSL_ASSERT_OK(destination.status());
  GenerateManifestStoreRequest request;
  request.mutable_actions()
      ->mutable_created()
      ->mutable_action_metadata()
      ->set_description("test only");
  ABSL_ASSERT_OK(writer_->Write(request, &source, &destination));
  ASSERT_TRUE(source.Close());
  ASSERT_TRUE(destination.Close());

  riegeli::StringReader result_reader(result);
  ABSL_ASSERT_OK(result_reader.status());

  EXPECT_THAT(Id3Extractor().ExtractManifestStoreLocation(result_reader, {}),
              IsOkAndHolds(Optional(AllOf(Field(&ByteRange::offset, Gt(0)),
                                          Field(&ByteRange::length, Gt(0))))));

  ASSERT_TRUE(result_reader.Seek(0));
  auto validation_result = validator_->Validate(result_reader, "audio/mpeg");
  ABSL_ASSERT_OK(validation_result);
  EXPECT_THAT(
      (*validation_result)->proto().active_manifest().validation().failures(),
      IsEmpty());
}

TEST_F(Id3WriterTest, WriteTwiceFails) {
  GenerateManifestStoreRequest request;
  request.mutable_actions()
      ->mutable_created()
      ->mutable_action_metadata()
      ->set_description("test only");

  std::string mp3_file_contents =
      std::string(kMp3FileWithNoId3Tag, sizeof(kMp3FileWithNoId3Tag));
  riegeli::StringReader source1(mp3_file_contents);
  ABSL_ASSERT_OK(source1.status());
  std::string result1;
  riegeli::StringWriter destination1(&result1);
  ABSL_ASSERT_OK(destination1.status());
  ABSL_ASSERT_OK(writer_->Write(request, &source1, &destination1));
  ASSERT_TRUE(source1.Close());
  ASSERT_TRUE(destination1.Close());

  riegeli::StringReader source2(result1);
  ABSL_ASSERT_OK(source2.status());
  std::string result2;
  riegeli::StringWriter destination2(&result2);
  ABSL_ASSERT_OK(destination2.status());
  EXPECT_THAT(
      writer_->Write(request, &source2, &destination2),
      StatusIs(absl::StatusCode::kAlreadyExists, HasSubstr("already exists")));
}

TEST_F(Id3WriterTest, WriteWithHardBindingFails) {
  std::string mp3_file_contents =
      std::string(kMp3FileWithNoId3Tag, sizeof(kMp3FileWithNoId3Tag));
  riegeli::StringReader source(mp3_file_contents);
  ABSL_ASSERT_OK(source.status());
  std::string result;
  riegeli::StringWriter destination(&result);
  ABSL_ASSERT_OK(destination.status());
  GenerateManifestStoreRequest request;
  request.mutable_actions()
      ->mutable_created()
      ->mutable_action_metadata()
      ->set_description("test only");
  request.mutable_hard_binding();
  EXPECT_THAT(writer_->Write(request, &source, &destination),
              StatusIs(absl::StatusCode::kInvalidArgument,
                       HasSubstr("must not include `hard_binding`")));
}

class BadTemplateSizeGenerator : public ManifestStoreGenerator {
 public:
  void GenerateManifestStore(
      GenerateManifestStoreRequest request, AsyncContext context,
      absl::AnyInvocable<void(absl::StatusOr<GenerateManifestStoreResponse>) &&>
          cb) const override {}

  void GenerateManifestStoreTemplate(
      GenerateManifestStoreRequest request, AsyncContext context,
      absl::AnyInvocable<void(absl::StatusOr<ManifestStoreTemplate>) &&> cb)
      const override {
    ManifestStoreTemplate t;
    t.set_manifest_store_size(-1);
    std::move(cb)(t);
  }

  void FinalizeManifestStore(
      FinalizeManifestStoreRequest request, AsyncContext context,
      absl::AnyInvocable<void(absl::StatusOr<FinalizeManifestStoreResponse>) &&>
          cb) const override {}
};

TEST_F(Id3WriterTest, WriteWithBadTemplateSizeFails) {
  BadTemplateSizeGenerator bad_generator;
  Id3Writer writer(&bad_generator);
  std::string mp3_file_contents =
      std::string(kMp3FileWithNoId3Tag, sizeof(kMp3FileWithNoId3Tag));
  riegeli::StringReader source(mp3_file_contents);
  std::string result;
  riegeli::StringWriter destination(&result);
  GenerateManifestStoreRequest request;
  request.mutable_actions()
      ->mutable_created()
      ->mutable_action_metadata()
      ->set_description("test only");
  EXPECT_THAT(writer.Write(request, &source, &destination),
              StatusIs(absl::StatusCode::kInvalidArgument,
                       HasSubstr("invalid manifest store template size")));
}

}  // namespace
}  // namespace credentio
