#include "fixture.h"

#include <maps/wikimap/mapspro/services/mrc/drive/firmware_updater/libs/db/include/common.h>
#include <maps/wikimap/mapspro/services/mrc/drive/firmware_updater/libs/db/include/branch_gateway.h>
#include <maps/wikimap/mapspro/services/mrc/drive/firmware_updater/libs/db/include/device_branch_gateway.h>

#include <maps/libs/introspection/include/comparison.h>
#include <maps/libs/introspection/include/stream_output.h>

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

namespace maps::fw_updater::db {
using introspection::operator==;
using introspection::operator!=;
using introspection::operator<<;
} // namespace maps::fw_updater::db

namespace maps::fw_updater::db::tests {

namespace {
const std::string HARDWARE = "nanopi-neo4";

const std::string DEVICE_A = "a";
const std::string DEVICE_B = "b";
} // namespace

TEST_F(Fixture, test_firmware_branch)
{
    Branches branches{{"stable"}, {"testing"}};
    {
        auto txn = txnHandle();
        BranchGateway{*txn}.insert(branches);
        txn->commit();
    }
    {
        auto txn = txnHandle();
        auto loadedBranches = BranchGateway{*txn}.load(
            sql_chemistry::orderBy(table::Branch::name));
        ASSERT_EQ(loadedBranches.size(), 2u);
        EXPECT_EQ(loadedBranches, branches);
    }
}

TEST_F(Fixture, test_firmware_device_branch)
{
    Branches branches{{"stable"}, {"testing"}};

    DeviceBranches deviceBranches {
        DeviceBranch(HARDWARE, DEVICE_A, "testing"),
        DeviceBranch(HARDWARE, DEVICE_B, "stable"),
    };

    {
        auto txn = txnHandle();
        BranchGateway{*txn}.insert(branches);
        DeviceBranchGateway{*txn}.insert(deviceBranches);
        txn->commit();
    }

    // Unique constraint violation
    {
        DeviceBranch deviceBranch(HARDWARE, DEVICE_A, "sable");
        EXPECT_THROW(DeviceBranchGateway{*txnHandle()}.insert(deviceBranch),
                     sql_chemistry::UniqueViolationError);
    }

    // Load
    {
        auto testingDevices = DeviceBranchGateway{*txnHandle()}.load(
            table::DeviceBranch::branch == "testing");
        ASSERT_EQ(testingDevices.size(), 1u);
        EXPECT_EQ(testingDevices[0], deviceBranches[0]);
    }

    // Update
    {
        auto txn = txnHandle();
        deviceBranches[0].setBranch("stable");
        DeviceBranchGateway{*txn}.update(deviceBranches[0]);
    }

    // Foreign key violation
    {
        deviceBranches[0].setBranch("unknown");
        EXPECT_THROW(DeviceBranchGateway{*txnHandle()}.update(deviceBranches[0]),
                     pqxx::sql_error);
    }

}

} // namespace maps::fw_updater::db::tests
