#include <sys/stat.h>
#include <string>
#include <fstream>
#include <experimental/filesystem>
#include <gtest/gtest.h>
#include <sdbusplus/bus.hpp>
#include "user.hpp"
namespace phosphor
{
namespace user
{

namespace fs = std::experimental::filesystem;

constexpr auto path = "/dummy/user";
constexpr auto testShadow = "/tmp/__tshadow__";
constexpr auto shadowCompare = "/tmp/__tshadowCompare__";

// New password
constexpr auto password = "passw0rd";

constexpr auto MD5 = "1";
constexpr auto SHA512 = "6";
constexpr auto salt = "1G.cK/YP";

// Example entry matching /etc/shadow structure
constexpr auto spPwdp = "$1$1G.cK/YP$JI5t0oliPxZveXOvLcZ/H.:17344:1:90:7:::";

class UserTest : public ::testing::Test
{
  public:
    const std::string md5Salt =
        '$' + std::string(MD5) + '$' + std::string(salt) + '$';
    const std::string shaSalt =
        '$' + std::string(SHA512) + '$' + std::string(salt) + '$';

    const std::string entry =
        fs::path(path).filename().string() + ':' + std::string(spPwdp);
    sdbusplus::bus::bus bus;
    phosphor::user::User user;

    // Gets called as part of each TEST_F construction
    UserTest() : bus(sdbusplus::bus::new_default()), user(bus, path)
    {
        // Create a shadow file entry
        std::ofstream file(testShadow);
        file << entry;
        file.close();

        // File to compare against
        std::ofstream compare(shadowCompare);
        compare << entry;
        compare.close();
    }

    // Gets called as part of each TEST_F destruction
    ~UserTest()
    {
        if (fs::exists(testShadow))
        {
            fs::remove(testShadow);
        }

        if (fs::exists(shadowCompare))
        {
            fs::remove(shadowCompare);
        }
    }

    /** @brief wrapper for get crypt field */
    auto getCryptField(char* data)
    {
        return User::getCryptField(std::forward<decltype(data)>(data));
    }

    /** @brief wrapper for getSaltString */
    auto getSaltString(const std::string& crypt, const std::string& salt)
    {
        return User::getSaltString(std::forward<decltype(crypt)>(crypt),
                                   std::forward<decltype(salt)>(salt));
    }

    /** @brief wrapper for generateHash */
    auto generateHash(const std::string& password, const std::string& salt)
    {
        return User::generateHash(std::forward<decltype(password)>(password),
                                  std::forward<decltype(salt)>(salt));
    }

    /** @brief Applies the new password */
    auto applyPassword()
    {
        return user.applyPassword(testShadow, password, salt);
    }
};

/** @brief Makes sure that SHA512 crypt field is extracted
 */
TEST_F(UserTest, sha512GetCryptField)
{
    auto salt = const_cast<char*>(shaSalt.c_str());
    EXPECT_EQ(SHA512, this->getCryptField(salt));
}

/** @brief Makes sure that MD5 crypt field is extracted as default
 */
TEST_F(UserTest, md55GetCryptFieldDefault)
{
    auto salt = const_cast<char*>("hello");
    EXPECT_EQ(MD5, this->getCryptField(salt));
}

/** @brief Makes sure that MD5 crypt field is extracted
 */
TEST_F(UserTest, md55GetCryptField)
{
    auto salt = const_cast<char*>(md5Salt.c_str());
    EXPECT_EQ(MD5, this->getCryptField(salt));
}

/** @brief Makes sure that salt string is put within $$
 */
TEST_F(UserTest, getSaltString)
{
    EXPECT_EQ(md5Salt, this->getSaltString(MD5, salt));
}

/** @brief Makes sure hash is generated correctly
 */
TEST_F(UserTest, generateHash)
{
    std::string sample = crypt(password, md5Salt.c_str());
    std::string actual = generateHash(password, md5Salt);
    EXPECT_EQ(sample, actual);
}

/** @brief Verifies that the correct password is written to file
 */
TEST_F(UserTest, applyPassword)
{
    // Update the password
    applyPassword();

    // Read files and compare
    std::ifstream shadow(testShadow);
    std::ifstream copy(shadowCompare);

    std::string shadowEntry;
    shadow >> shadowEntry;

    std::string shadowCompareEntry;
    copy >> shadowCompareEntry;

    EXPECT_EQ(shadowEntry, shadowCompareEntry);
}

/** @brief Verifies the permissions are correct
 */
TEST_F(UserTest, verifyShadowPermission)
{
    // Change the permission to 400-> -r--------
    chmod(testShadow, S_IRUSR);
    chmod(shadowCompare, S_IRUSR);

    // Update the password so that the temp file is in action
    applyPassword();

    // Compare the permission of 2 files.
    // file rename would make sure that the permissions
    // of old are moved to new
    struct stat shadow
    {
    };
    struct stat compare
    {
    };

    stat(testShadow, &shadow);
    stat(shadowCompare, &compare);
    EXPECT_EQ(shadow.st_mode, compare.st_mode);
}

} // namespace user
} // namespace phosphor
