#include "dbus_environment.hpp"
#include "messages/update_report_ind.hpp"
#include "trigger_actions.hpp"
#include "utils/messanger.hpp"

#include <stdexcept>

#include <gmock/gmock.h>

using namespace testing;

namespace action
{
namespace numeric
{
using LogParam = std::tuple<::numeric::Type, double, double>;

static auto getCorrectParams()
{
    return Values(std::make_tuple(::numeric::Type::upperCritical, 91.1, 90),
                  std::make_tuple(::numeric::Type::lowerCritical, 91.2, 90),
                  std::make_tuple(::numeric::Type::upperWarning, 88.5, 90),
                  std::make_tuple(::numeric::Type::lowerWarning, 88.6, 90));
}

static auto getIncorrectParams()
{
    return Values(
        std::make_tuple(::numeric::Type::upperCritical, 90.0, 90),
        std::make_tuple(static_cast<::numeric::Type>(-1), 88.0, 90),
        std::make_tuple(static_cast<::numeric::Type>(123), 123.0, 90));
}

template <typename ActionType>
class TestActionNumeric : public Test, public WithParamInterface<LogParam>
{
  public:
    void SetUp() override
    {
        auto [type, threshold, value] = GetParam();
        sut = std::make_unique<ActionType>(type, threshold);
        commmitValue = value;
    }

    void commit()
    {
        sut->commit("MyTrigger", std::nullopt, "MySensor",
                    Milliseconds{100'000}, commmitValue);
    }

    std::unique_ptr<ActionType> sut;
    double commmitValue;
};

class TestLogToJournalNumeric : public TestActionNumeric<LogToJournal>
{};

INSTANTIATE_TEST_SUITE_P(LogToJournalNumericParams, TestLogToJournalNumeric,
                         getCorrectParams());

TEST_P(TestLogToJournalNumeric, commitAnActionDoesNotThrow)
{
    EXPECT_NO_THROW(commit());
}

class TestLogToJournalNumericThrow : public TestLogToJournalNumeric
{};

INSTANTIATE_TEST_SUITE_P(_, TestLogToJournalNumericThrow, getIncorrectParams());

TEST_P(TestLogToJournalNumericThrow, commitAnActionExpectThrow)
{
    EXPECT_ANY_THROW(commit());
}

class TestLogToRedfishEventLogNumeric :
    public TestActionNumeric<LogToRedfishEventLog>
{};

INSTANTIATE_TEST_SUITE_P(LogToRedfishEventLogNumericParams,
                         TestLogToRedfishEventLogNumeric, getCorrectParams());

TEST_P(TestLogToRedfishEventLogNumeric, commitExpectNoThrow)
{
    EXPECT_NO_THROW(commit());
}

class TestLogToRedfishEventLogNumericThrow :
    public TestLogToRedfishEventLogNumeric
{};

INSTANTIATE_TEST_SUITE_P(_, TestLogToRedfishEventLogNumericThrow,
                         getIncorrectParams());

TEST_P(TestLogToRedfishEventLogNumericThrow, commitExpectToThrow)
{
    EXPECT_ANY_THROW(commit());
}

} // namespace numeric

namespace discrete
{
using LogParam = std::tuple<::discrete::Severity, TriggerValue>;

static auto getCorrectParams()
{
    return Values(
        std::make_tuple(::discrete::Severity::critical,
                        TriggerValue("DiscreteVal")),
        std::make_tuple(::discrete::Severity::warning, TriggerValue("On")),
        std::make_tuple(::discrete::Severity::ok, TriggerValue("Off")));
}

static auto getIncorrectParams()
{
    return Values(
        std::make_tuple(static_cast<::discrete::Severity>(-1),
                        TriggerValue("DiscreteVal42")),
        std::make_tuple(static_cast<::discrete::Severity>(42),
                        TriggerValue("On")),
        std::make_tuple(::discrete::Severity::critical, TriggerValue(42.0)),
        std::make_tuple(::discrete::Severity::warning, TriggerValue(0.0)),
        std::make_tuple(::discrete::Severity::ok, TriggerValue(0.1)));
}

template <typename ActionType>
class TestActionDiscrete : public Test, public WithParamInterface<LogParam>
{
  public:
    void SetUp() override
    {
        auto [severity, value] = GetParam();
        sut = std::make_unique<ActionType>(severity);
        commitValue = value;
    }

    void commit()
    {
        std::string thresholdName = "MyThreshold";
        sut->commit("MyTrigger", std::cref(thresholdName), "MySensor",
                    Milliseconds{100'000}, commitValue);
    }

    TriggerValue commitValue;
    std::unique_ptr<ActionType> sut;
};

class TestLogToJournalDiscrete : public TestActionDiscrete<LogToJournal>
{};

INSTANTIATE_TEST_SUITE_P(LogToJournalDiscreteParams, TestLogToJournalDiscrete,
                         getCorrectParams());

TEST_P(TestLogToJournalDiscrete, commitAnActionWIthDiscreteValueDoesNotThrow)
{
    EXPECT_NO_THROW(commit());
}

class TestLogToJournalDiscreteThrow : public TestLogToJournalDiscrete
{};

INSTANTIATE_TEST_SUITE_P(_, TestLogToJournalDiscreteThrow,
                         getIncorrectParams());

TEST_P(TestLogToJournalDiscreteThrow, commitAnActionExpectThrow)
{
    EXPECT_ANY_THROW(commit());
}

class TestLogToRedfishEventLogDiscrete :
    public TestActionDiscrete<LogToRedfishEventLog>
{};

INSTANTIATE_TEST_SUITE_P(LogToRedfishEventLogDiscreteParams,
                         TestLogToRedfishEventLogDiscrete, getCorrectParams());

TEST_P(TestLogToRedfishEventLogDiscrete, commitExpectNoThrow)
{
    EXPECT_NO_THROW(commit());
}

class TestLogToRedfishEventLogDiscreteThrow :
    public TestLogToRedfishEventLogDiscrete
{};

INSTANTIATE_TEST_SUITE_P(_, TestLogToRedfishEventLogDiscreteThrow,
                         getIncorrectParams());

TEST_P(TestLogToRedfishEventLogDiscreteThrow, commitExpectToThrow)
{
    EXPECT_ANY_THROW(commit());
}

namespace onChange
{

template <typename ActionType>
class TestActionOnChange : public Test
{
  public:
    void SetUp() override
    {
        sut = std::make_unique<ActionType>();
    }

    void commit(TriggerValue value)
    {
        sut->commit("MyTrigger", std::nullopt, "MySensor",
                    Milliseconds{100'000}, value);
    }

    std::unique_ptr<ActionType> sut;
};

class TestLogToJournalDiscreteOnChange : public TestActionOnChange<LogToJournal>
{};

TEST_F(TestLogToJournalDiscreteOnChange, commitNumericValueExpectNoThrow)
{
    EXPECT_NO_THROW(commit(90.0));
}

TEST_F(TestLogToJournalDiscreteOnChange, commitDiscreteValueExpectNoThrow)
{
    EXPECT_NO_THROW(commit("Off"));
}

class TestLogToRedfishEventLogDiscreteOnChange :
    public TestActionOnChange<LogToRedfishEventLog>
{};

TEST_F(TestLogToRedfishEventLogDiscreteOnChange,
       commitNumericValueExpectNoThrow)
{
    EXPECT_NO_THROW(commit(90.0));
}

TEST_F(TestLogToRedfishEventLogDiscreteOnChange,
       commitDiscreteValueExpectNoThrow)
{
    EXPECT_NO_THROW(commit("Off"));
}

} // namespace onChange
} // namespace discrete

class TestUpdateReport : public Test
{
  public:
    TestUpdateReport() : messanger(DbusEnvironment::getIoc())
    {}

    void make(std::vector<std::string> names)
    {
        messanger.on_receive<messages::UpdateReportInd>(
            [this](const auto& msg) { updateReport.Call(msg); });

        sut = std::make_unique<UpdateReport>(
            DbusEnvironment::getIoc(),
            std::make_shared<std::vector<std::string>>(std::move(names)));
    }

    void commit(TriggerValue value)
    {
        sut->commit(triggerId, std::nullopt, "MySensor", Milliseconds{100'000},
                    value);
    }

    utils::Messanger messanger;
    NiceMock<MockFunction<void(const messages::UpdateReportInd&)>> updateReport;
    std::unique_ptr<UpdateReport> sut;
    std::string triggerId = "MyTrigger";
};

TEST_F(TestUpdateReport, commitWhenReportNameIsEmptyExpectNoReportUpdate)
{
    EXPECT_CALL(updateReport, Call(_)).Times(0);

    make({});
    commit(90.0);
}

TEST_F(TestUpdateReport, commitExpectReportUpdate)
{
    std::vector<std::string> names = {"Report1", "Report2", "Report3"};
    EXPECT_CALL(updateReport,
                Call(FieldsAre(UnorderedElementsAreArray(names))));

    make(names);
    commit(90.0);
}

} // namespace action
