/*
 * Copyright 2025 Bloomberg Finance LP
 *
 * 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 <fcntl.h>
#include <gmock/gmock.h>
#include <unistd.h>

#include <buildboxcasd_fslocalactionstorage.h>
#include <buildboxcasd_fslocalassetstorage.h>
#include <buildboxcasd_server.h>
#include <buildboxcommon_fslocalcas.h>

using namespace buildboxcasd;
using namespace buildboxcommon;

const std::string TEST_INSTANCE_NAME = "testInstances/instance1";

const auto digestFunctionInitializer = []() {
    buildboxcommon::DigestGenerator::init();
    return 0;
}();

class LocalCasServerFixture : public ::testing::Test {
  protected:
    LocalCasServerFixture()
        : TEST_SERVER_ADDRESS("unix://" +
                              std::string(socket_directory.name()) +
                              "/proxy.sock"),
          storage(std::make_shared<FsLocalCas>(storage_root_directory.name())),
          asset_storage(std::make_shared<FsLocalAssetStorage>(
              storage_root_directory.name())),
          action_storage(std::make_shared<FsLocalActionStorage>(
              storage_root_directory.name())),
          server(std::make_shared<Server>(storage, asset_storage,
                                          action_storage)),
          grpc_client(std::make_shared<GrpcClient>()),
          cas_client(std::make_shared<CASClient>(grpc_client))
    {
        // Building and starting a server:
        server->addLocalServerInstance(TEST_INSTANCE_NAME);
        server->addListeningPort(TEST_SERVER_ADDRESS);
        server->start();

        ConnectionOptions options;
        options.d_url = TEST_SERVER_ADDRESS;
        options.d_instanceName = TEST_INSTANCE_NAME;
        grpc_client->init(options);
        cas_client->init();
    }

    buildboxcommon::TemporaryDirectory socket_directory;
    const std::string TEST_SERVER_ADDRESS;

    buildboxcommon::TemporaryDirectory storage_root_directory;
    std::shared_ptr<FsLocalCas> storage;
    std::shared_ptr<FsLocalAssetStorage> asset_storage;
    std::shared_ptr<FsLocalActionStorage> action_storage;
    std::shared_ptr<Server> server;

    std::shared_ptr<GrpcClient> grpc_client;
    std::shared_ptr<CASClient> cas_client;
};

TEST_F(LocalCasServerFixture, TestGetLocalServerDetails)
{
    const auto response = cas_client->localServerDetails();

    constexpr int HOSTNAME_MAX = 256;
    char hostname[HOSTNAME_MAX] = {0};
    gethostname(hostname, sizeof(hostname));

    ASSERT_TRUE(response.has_value());
    if (response.has_value()) {
        ASSERT_EQ(response->hostname(), hostname);
        ASSERT_EQ(response->process_uid(), getuid());
        ASSERT_EQ(response->storage_root(), storage->path());
    }
}
