// Copyright 2025 Bloomberg Finance L.P
//
// 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
//
//     http://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 <processargs.h>

#include <gtest/gtest.h>

using namespace casupload_oci;

TEST(ProcessArgsTest, ValidOciUri)
{
    const char *argv[] = {"casupload-oci", "docker.io/alpine:latest"};
    int argc = sizeof(argv) / sizeof(argv[0]);

    ProcessedArgs args = processArgs(argc, const_cast<char **>(argv));

    EXPECT_FALSE(args.d_processed);
    EXPECT_TRUE(args.d_valid);
    EXPECT_EQ(args.d_ociUri, "docker.io/alpine:latest");
}

TEST(ProcessArgsTest, OutputFiles)
{
    const char *argv[] = {"casupload-oci", "--output-digest-file=root.txt",
                          "--output-tree-digest-file=tree.txt",
                          "--num-parallel-layer-threads=4",
                          "docker.io/alpine:latest"};
    int argc = sizeof(argv) / sizeof(argv[0]);

    ProcessedArgs args = processArgs(argc, const_cast<char **>(argv));

    EXPECT_FALSE(args.d_processed);
    EXPECT_TRUE(args.d_valid);
    EXPECT_EQ(args.d_ociUri, "docker.io/alpine:latest");
    EXPECT_EQ(args.d_outputRootDigestFile, "root.txt");
    EXPECT_EQ(args.d_outputTreeDigestFile, "tree.txt");
    EXPECT_EQ(args.d_numParallelLayerThreads, 4);
}

TEST(ProcessArgsTest, MissingOciUri)
{
    const char *argv[] = {"casupload-oci"};
    int argc = sizeof(argv) / sizeof(argv[0]);

    ProcessedArgs args = processArgs(argc, const_cast<char **>(argv));

    EXPECT_FALSE(args.d_processed);
    EXPECT_FALSE(args.d_valid);
}

TEST(ProcessArgsTest, HelpFlag)
{
    const char *argv[] = {"casupload-oci", "--help"};
    int argc = sizeof(argv) / sizeof(argv[0]);

    ProcessedArgs args = processArgs(argc, const_cast<char **>(argv));

    EXPECT_TRUE(args.d_processed);
    EXPECT_FALSE(args.d_valid);
}

TEST(ProcessArgsTest, VersionFlag)
{
    const char *argv[] = {"casupload-oci", "--version"};
    int argc = sizeof(argv) / sizeof(argv[0]);

    ProcessedArgs args = processArgs(argc, const_cast<char **>(argv));

    EXPECT_TRUE(args.d_processed);
    EXPECT_FALSE(args.d_valid);
}

TEST(ProcessArgsTest, BaseConnectionOptions)
{
    const char *argv[] = {"casupload-oci", "--remote=http://localhost:50051",
                          "--instance=test-instance",
                          "docker.io/alpine:latest"};
    int argc = sizeof(argv) / sizeof(argv[0]);

    ProcessedArgs args = processArgs(argc, const_cast<char **>(argv));

    EXPECT_FALSE(args.d_processed);
    EXPECT_TRUE(args.d_valid);
    EXPECT_EQ(args.d_ociUri, "docker.io/alpine:latest");
    EXPECT_EQ(args.d_casConnectionOptions.d_url, "http://localhost:50051");
    EXPECT_EQ(args.d_casConnectionOptions.d_instanceName, "test-instance");
    EXPECT_EQ(args.d_assetConnectionOptions.d_url, "http://localhost:50051");
    EXPECT_EQ(args.d_assetConnectionOptions.d_instanceName, "test-instance");
}

TEST(ProcessArgsTest, CasOverrideOptions)
{
    const char *argv[] = {"casupload-oci",
                          "--remote=http://localhost:50051",
                          "--instance=test-instance",
                          "--cas-remote=http://cas-server:8080",
                          "--cas-instance=cas-instance",
                          "docker.io/alpine:latest"};
    int argc = sizeof(argv) / sizeof(argv[0]);

    ProcessedArgs args = processArgs(argc, const_cast<char **>(argv));

    EXPECT_FALSE(args.d_processed);
    EXPECT_TRUE(args.d_valid);
    EXPECT_EQ(args.d_ociUri, "docker.io/alpine:latest");
    EXPECT_EQ(args.d_casConnectionOptions.d_url, "http://cas-server:8080");
    EXPECT_EQ(args.d_casConnectionOptions.d_instanceName, "cas-instance");
    EXPECT_EQ(args.d_assetConnectionOptions.d_url, "http://localhost:50051");
    EXPECT_EQ(args.d_assetConnectionOptions.d_instanceName, "test-instance");
}

TEST(ProcessArgsTest, RaOverrideOptions)
{
    const char *argv[] = {"casupload-oci",
                          "--remote=http://localhost:50051",
                          "--instance=test-instance",
                          "--ra-remote=http://asset-server:9090",
                          "--ra-instance=asset-instance",
                          "docker.io/alpine:latest"};
    int argc = sizeof(argv) / sizeof(argv[0]);

    ProcessedArgs args = processArgs(argc, const_cast<char **>(argv));

    EXPECT_FALSE(args.d_processed);
    EXPECT_TRUE(args.d_valid);
    EXPECT_EQ(args.d_ociUri, "docker.io/alpine:latest");
    EXPECT_EQ(args.d_casConnectionOptions.d_url, "http://localhost:50051");
    EXPECT_EQ(args.d_casConnectionOptions.d_instanceName, "test-instance");
    EXPECT_EQ(args.d_assetConnectionOptions.d_url, "http://asset-server:9090");
    EXPECT_EQ(args.d_assetConnectionOptions.d_instanceName, "asset-instance");
}

TEST(ProcessArgsTest, BothServiceOverrides)
{
    const char *argv[] = {"casupload-oci",
                          "--remote=http://localhost:50051",
                          "--instance=test-instance",
                          "--cas-remote=http://cas-server:8080",
                          "--cas-instance=cas-instance",
                          "--ra-remote=http://asset-server:9090",
                          "--ra-instance=asset-instance",
                          "docker.io/alpine:latest"};
    int argc = sizeof(argv) / sizeof(argv[0]);

    ProcessedArgs args = processArgs(argc, const_cast<char **>(argv));

    EXPECT_FALSE(args.d_processed);
    EXPECT_TRUE(args.d_valid);
    EXPECT_EQ(args.d_ociUri, "docker.io/alpine:latest");
    EXPECT_EQ(args.d_casConnectionOptions.d_url, "http://cas-server:8080");
    EXPECT_EQ(args.d_casConnectionOptions.d_instanceName, "cas-instance");
    EXPECT_EQ(args.d_assetConnectionOptions.d_url, "http://asset-server:9090");
    EXPECT_EQ(args.d_assetConnectionOptions.d_instanceName, "asset-instance");
}
