#include "fixture.h"

#include <maps/wikimap/mapspro/services/mrc/drive/firmware_updater/storage/lib/s3/client.h>
#include <maps/wikimap/mapspro/services/mrc/drive/firmware_updater/libs/unittest/include/unittest_config.h>

#include <library/cpp/testing/gtest/gtest.h>

namespace maps::fw_updater::storage::s3::tests {

using Fixture = storage::tests::Fixture;

constexpr size_t MB = 1024 * 1024;

TEST_F(Fixture, test_multipart_upload)
{
    const std::string KEY = "test-key";
    auto& s3Client = configuration()->s3Client();

    auto uploadId = s3Client.createMultipartUpload(KEY);
    EXPECT_FALSE(uploadId.empty());

    // Minimum size of non-last uploaded part is 5 Mb
    std::vector<std::string> parts{std::string(5 * MB, 'a'),
                                   std::string(5 * MB, 'b'),
                                   std::string(1 * MB, 'c')};
    std::string fullData;
    int partNumber = 1;
    std::vector<Aws::S3::Model::CompletedPart> completedParts;

    for (const auto& part : parts) {
        std::stringbuf partBuf(part);
        auto completedPart = s3Client.uploadPart(KEY, uploadId, partNumber, partBuf);
        completedParts.push_back(std::move(completedPart));

        ++partNumber;
        fullData += part;
    }

    s3Client.completeMultipartUpload(KEY, uploadId, completedParts);

    auto objectHolder = s3Client.getObject(KEY);

    auto& stream = objectHolder.getBody();
    auto body = std::string(std::istreambuf_iterator<char>(stream),
                            std::istreambuf_iterator<char>());

    EXPECT_EQ(fullData, body);
}

TEST_F(Fixture, test_abort_multipart_upload)
{
    const std::string KEY = "test-key-2";

    auto& s3Client = configuration()->s3Client();

    auto uploadId = s3Client.createMultipartUpload(KEY);

    std::string part(5 * MB, 'a');
    std::stringbuf partBuf(part);
    s3Client.uploadPart(KEY, uploadId, 1, partBuf);

    s3Client.abortMultipartUpload(KEY, uploadId);

    EXPECT_THROW(s3Client.getObject(KEY), maps::RuntimeError);
}

} // namespace maps::fw_updater::storage::s3:tests
