#include "trigger_manager.hpp"

#include "trigger.hpp"
#include "types/trigger_types.hpp"
#include "utils/conversion_trigger.hpp"
#include "utils/dbus_path_utils.hpp"
#include "utils/make_id_name.hpp"
#include "utils/transform.hpp"
#include "utils/tstring.hpp"

#include <phosphor-logging/log.hpp>

#include <unordered_set>

TriggerManager::TriggerManager(
    std::unique_ptr<interfaces::TriggerFactory> triggerFactoryIn,
    std::unique_ptr<interfaces::JsonStorage> triggerStorageIn,
    const std::shared_ptr<sdbusplus::asio::object_server>& objServer) :
    triggerFactory(std::move(triggerFactoryIn)),
    triggerStorage(std::move(triggerStorageIn))
{
    loadFromPersistent();

    managerIface = objServer->add_unique_interface(
        triggerManagerPath, triggerManagerIfaceName, [this](auto& iface) {
        iface.register_method(
            "AddTrigger",
            [this](boost::asio::yield_context& yield, const std::string& id,
                   const std::string& name,
                   const std::vector<std::string>& triggerActions,
                   const SensorsInfo& sensors,
                   const std::vector<sdbusplus::message::object_path>& reports,
                   const TriggerThresholdParamsExt& thresholds) {
            LabeledTriggerThresholdParams labeledTriggerThresholdParams =
                std::visit(utils::ToLabeledThresholdParamConversion(),
                           thresholds);

            std::vector<LabeledSensorInfo> labeledSensorsInfo =
                triggerFactory->getLabeledSensorsInfo(yield, sensors);

            auto reportIds = utils::transform<std::vector>(
                reports,
                [](const auto& item) { return utils::reportPathToId(item); });

            return addTrigger(id, name, triggerActions, labeledSensorsInfo,
                              reportIds, labeledTriggerThresholdParams)
                .getPath();
        });
    });
}

void TriggerManager::removeTrigger(const interfaces::Trigger* trigger)
{
    triggers.erase(
        std::remove_if(triggers.begin(), triggers.end(),
                       [trigger](const auto& x) { return trigger == x.get(); }),
        triggers.end());
}

void TriggerManager::verifyReportIds(
    const std::vector<std::string>& newReportIds)
{
    if (std::unordered_set(newReportIds.begin(), newReportIds.end()).size() !=
        newReportIds.size())
    {
        throw sdbusplus::exception::SdBusError(
            static_cast<int>(std::errc::invalid_argument),
            "Duplicate element in ReportIds");
    }
}

void TriggerManager::verifyThresholdParams(
    const LabeledTriggerThresholdParams& thresholdParams)
{
    namespace ts = utils::tstring;

    if (auto discreteParams =
            std::get_if<std::vector<discrete::LabeledThresholdParam>>(
                &thresholdParams);
        discreteParams != nullptr)
    {
        for (auto discreteParam : *discreteParams)
        {
            if (discreteParam.at_label<ts::UserId>().length() >
                utils::constants::maxIdNameLength)
            {
                throw errors::InvalidArgument("ThresholdParams.Id",
                                              "UserId too long.");
            }
        }
    }
}

void TriggerManager::verifyAddTrigger(
    const std::vector<std::string>& reportIds,
    const LabeledTriggerThresholdParams& thresholdParams) const
{
    if (triggers.size() >= maxTriggers)
    {
        throw sdbusplus::exception::SdBusError(
            static_cast<int>(std::errc::too_many_files_open),
            "Reached maximal trigger count");
    }

    verifyReportIds(reportIds);
    verifyThresholdParams(thresholdParams);
}

interfaces::Trigger& TriggerManager::addTrigger(
    const std::string& triggerIdIn, const std::string& triggerNameIn,
    const std::vector<std::string>& triggerActions,
    const std::vector<LabeledSensorInfo>& labeledSensorsInfo,
    const std::vector<std::string>& reportIds,
    const LabeledTriggerThresholdParams& labeledThresholdParams)
{
    const auto existingTriggerIds = utils::transform(
        triggers, [](const auto& trigger) { return trigger->getId(); });

    auto [id, name] = utils::makeIdName(triggerIdIn, triggerNameIn,
                                        triggerNameDefault, existingTriggerIds);

    verifyAddTrigger(reportIds, labeledThresholdParams);

    triggers.emplace_back(triggerFactory->make(
        id, name, triggerActions, reportIds, *this, *triggerStorage,
        labeledThresholdParams, labeledSensorsInfo));

    return *triggers.back();
}

void TriggerManager::loadFromPersistent()
{
    std::vector<interfaces::JsonStorage::FilePath> paths =
        triggerStorage->list();

    for (const auto& path : paths)
    {
        std::optional<nlohmann::json> data = triggerStorage->load(path);
        try
        {
            if (!data.has_value())
            {
                throw std::runtime_error("Empty storage");
            }
            size_t version = data->at("Version").get<size_t>();
            if (version != Trigger::triggerVersion)
            {
                throw std::runtime_error("Invalid version");
            }
            const std::string& id = data->at("Id").get_ref<std::string&>();
            const std::string& name = data->at("Name").get_ref<std::string&>();
            int thresholdParamsDiscriminator =
                data->at("ThresholdParamsDiscriminator").get<int>();
            const std::vector<std::string> triggerActions =
                data->at("TriggerActions").get<std::vector<std::string>>();

            LabeledTriggerThresholdParams labeledThresholdParams;
            if (0 == thresholdParamsDiscriminator)
            {
                labeledThresholdParams =
                    data->at("ThresholdParams")
                        .get<std::vector<numeric::LabeledThresholdParam>>();
            }
            else
            {
                labeledThresholdParams =
                    data->at("ThresholdParams")
                        .get<std::vector<discrete::LabeledThresholdParam>>();
            }

            auto reportIds =
                data->at("ReportIds").get<std::vector<std::string>>();

            auto labeledSensorsInfo =
                data->at("Sensors").get<std::vector<LabeledSensorInfo>>();

            addTrigger(id, name, triggerActions, labeledSensorsInfo, reportIds,
                       labeledThresholdParams);
        }
        catch (const std::exception& e)
        {
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "Failed to load trigger from storage",
                phosphor::logging::entry(
                    "FILENAME=%s",
                    static_cast<std::filesystem::path>(path).c_str()),
                phosphor::logging::entry("EXCEPTION_MSG=%s", e.what()));
            triggerStorage->remove(path);
        }
    }
}
