#include "report_manager.hpp"

#include "report.hpp"
#include "types/report_types.hpp"
#include "utils/conversion.hpp"
#include "utils/dbus_path_utils.hpp"
#include "utils/make_id_name.hpp"
#include "utils/transform.hpp"

#include <phosphor-logging/log.hpp>
#include <sdbusplus/exception.hpp>
#include <sdbusplus/unpack_properties.hpp>

#include <optional>
#include <stdexcept>
#include <system_error>

ReadingParameters
    convertToReadingParameters(ReadingParametersPastVersion params)
{
    return utils::transform(params, [](const auto& param) {
        using namespace std::chrono_literals;

        const auto& [sensorPath, operationType, id, metadata] = param;

        return ReadingParameters::value_type(
            std::vector<
                std::tuple<sdbusplus::message::object_path, std::string>>{
                {sensorPath, metadata}},
            operationType, id, utils::enumToString(CollectionTimeScope::point),
            0u);
    });
}

ReportManager::ReportManager(
    std::unique_ptr<interfaces::ReportFactory> reportFactoryIn,
    std::unique_ptr<interfaces::JsonStorage> reportStorageIn,
    const std::shared_ptr<sdbusplus::asio::object_server>& objServerIn) :
    reportFactory(std::move(reportFactoryIn)),
    reportStorage(std::move(reportStorageIn)), objServer(objServerIn)
{
    reports.reserve(maxReports);

    loadFromPersistent();

    reportManagerIface = objServer->add_unique_interface(
        reportManagerPath, reportManagerIfaceName, [this](auto& dbusIface) {
            dbusIface.register_property_r(
                "MaxReports", size_t{}, sdbusplus::vtable::property_::const_,
                [](const auto&) { return maxReports; });
            dbusIface.register_property_r(
                "MinInterval", uint64_t{}, sdbusplus::vtable::property_::const_,
                [](const auto&) -> uint64_t { return minInterval.count(); });
            dbusIface.register_property_r(
                "SupportedOperationTypes", std::vector<std::string>{},
                sdbusplus::vtable::property_::const_,
                [](const auto&) -> std::vector<std::string> {
                    return utils::transform<std::vector>(
                        utils::convDataOperationType, [](const auto& item) {
                            return std::string(item.first);
                        });
                });

            dbusIface.register_method(
                "AddReport", [this](boost::asio::yield_context& yield,
                                    const std::string& reportId,
                                    const std::string& reportingType,
                                    const bool emitsReadingsUpdate,
                                    const bool logToMetricReportsCollection,
                                    const uint64_t interval,
                                    ReadingParametersPastVersion metricParams) {
                    constexpr auto enabledDefault = true;
                    constexpr ReportUpdates reportUpdatesDefault =
                        ReportUpdates::overwrite;

                    std::vector<ReportAction> reportActions;

                    if (emitsReadingsUpdate)
                    {
                        reportActions.emplace_back(
                            ReportAction::emitsReadingsUpdate);
                    }
                    if (logToMetricReportsCollection)
                    {
                        reportActions.emplace_back(
                            ReportAction::logToMetricReportsCollection);
                    }

                    return addReport(yield, reportId, reportId,
                                     utils::toReportingType(reportingType),
                                     reportActions, Milliseconds(interval),
                                     maxAppendLimit, reportUpdatesDefault,
                                     convertToReadingParameters(
                                         std::move(metricParams)),
                                     enabledDefault)
                        .getPath();
                });

            dbusIface.register_method(
                "AddReportFutureVersion",
                [this](
                    boost::asio::yield_context& yield,
                    const std::vector<
                        std::pair<std::string, AddReportFutureVersionVariant>>&
                        properties) {
                    std::optional<std::string> reportId;
                    std::optional<std::string> reportName;
                    std::optional<std::string> reportingType;
                    std::optional<std::vector<std::string>> reportActions;
                    std::optional<uint64_t> interval;
                    std::optional<uint64_t> appendLimit;
                    std::optional<std::string> reportUpdates;
                    std::optional<ReadingParameters> metricParams;
                    std::optional<ReadingParameters> readingParameters;
                    std::optional<bool> enabled;

                    try
                    {
                        sdbusplus::unpackProperties(
                            properties, "Id", reportId, "Name", reportName,
                            "ReportingType", reportingType, "ReportActions",
                            reportActions, "Interval", interval, "AppendLimit",
                            appendLimit, "ReportUpdates", reportUpdates,
                            "MetricParams", metricParams, "Enabled", enabled,
                            "ReadingParameters", readingParameters);
                    }
                    catch (const sdbusplus::exception::UnpackPropertyError& e)
                    {
                        throw errors::InvalidArgument(e.propertyName);
                    }

                    if (readingParameters == std::nullopt)
                    {
                        readingParameters = metricParams;
                    }

                    return addReport(
                               yield, reportId.value_or(""),
                               reportName.value_or(""),
                               utils::toReportingType(
                                   reportingType.value_or(utils::enumToString(
                                       ReportingType::onRequest))),
                               utils::transform(
                                   reportActions.value_or(
                                       std::vector<std::string>{}),
                                   [](const auto& reportAction) {
                                       return utils::toReportAction(
                                           reportAction);
                                   }),
                               Milliseconds(interval.value_or(0)),
                               appendLimit.value_or(maxAppendLimit),
                               utils::toReportUpdates(
                                   reportUpdates.value_or(utils::enumToString(
                                       ReportUpdates::overwrite))),
                               readingParameters.value_or(ReadingParameters{}),
                               enabled.value_or(true))
                        .getPath();
                });
        });
}

void ReportManager::removeReport(const interfaces::Report* report)
{
    reports.erase(
        std::remove_if(reports.begin(), reports.end(),
                       [report](const auto& x) { return report == x.get(); }),
        reports.end());
}

void ReportManager::verifyMetricParameters(
    const std::vector<LabeledMetricParameters>& readingParams)
{
    namespace ts = utils::tstring;

    for (auto readingParam : readingParams)
    {
        if (readingParam.at_label<ts::Id>().length() >
            utils::constants::maxIdNameLength)
        {
            throw errors::InvalidArgument("ReadingParameters.Id", "Too long.");
        }
    }
}

void ReportManager::verifyAddReport(
    const std::string& reportId, const std::string& reportName,
    const ReportingType reportingType, Milliseconds interval,
    const ReportUpdates reportUpdates, const uint64_t appendLimit,
    const std::vector<LabeledMetricParameters>& readingParams)
{
    namespace ts = utils::tstring;

    if (reports.size() >= maxReports)
    {
        throw sdbusplus::exception::SdBusError(
            static_cast<int>(std::errc::too_many_files_open),
            "Reached maximal report count");
    }

    if (appendLimit > maxAppendLimit &&
        appendLimit != std::numeric_limits<uint64_t>::max())
    {
        throw errors::InvalidArgument("AppendLimit", "Out of range.");
    }

    if ((reportingType == ReportingType::periodic && interval < minInterval) ||
        (reportingType != ReportingType::periodic &&
         interval != Milliseconds{0}))
    {
        throw errors::InvalidArgument("Interval");
    }

    size_t metricCount = 0;
    for (auto metricParam : readingParams)
    {
        auto metricParamsVec =
            metricParam.at_label<utils::tstring::SensorPath>();
        metricCount += metricParamsVec.size();
    }

    if (readingParams.size() > maxNumberMetrics ||
        metricCount > maxNumberMetrics)
    {
        throw errors::InvalidArgument("MetricParams", "Too many.");
    }

    verifyMetricParameters(readingParams);

    for (const LabeledMetricParameters& item : readingParams)
    {
        utils::toOperationType(
            utils::toUnderlying(item.at_label<ts::OperationType>()));
    }
}

interfaces::Report& ReportManager::addReport(
    boost::asio::yield_context& yield, const std::string& reportId,
    const std::string& reportName, const ReportingType reportingType,
    const std::vector<ReportAction>& reportActions, Milliseconds interval,
    const uint64_t appendLimit, const ReportUpdates reportUpdates,
    ReadingParameters metricParams, const bool enabled)
{
    auto labeledMetricParams =
        reportFactory->convertMetricParams(yield, metricParams);

    return addReport(reportId, reportName, reportingType, reportActions,
                     interval, appendLimit, reportUpdates,
                     std::move(labeledMetricParams), enabled, Readings{});
}

interfaces::Report& ReportManager::addReport(
    const std::string& reportId, const std::string& reportName,
    const ReportingType reportingType,
    const std::vector<ReportAction>& reportActions, Milliseconds interval,
    const uint64_t appendLimit, const ReportUpdates reportUpdates,
    std::vector<LabeledMetricParameters> labeledMetricParams,
    const bool enabled, Readings readings)
{
    const auto existingReportIds = utils::transform(
        reports, [](const auto& report) { return report->getId(); });

    auto [id, name] = utils::makeIdName(reportId, reportName, reportNameDefault,
                                        existingReportIds);

    verifyAddReport(id, name, reportingType, interval, reportUpdates,
                    appendLimit, labeledMetricParams);

    reports.emplace_back(
        reportFactory->make(id, name, reportingType, reportActions, interval,
                            appendLimit, reportUpdates, *this, *reportStorage,
                            labeledMetricParams, enabled, std::move(readings)));
    return *reports.back();
}

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

    for (const auto& path : paths)
    {
        std::optional<nlohmann::json> data = reportStorage->load(path);
        try
        {
            size_t version = data->at("Version").get<size_t>();
            if (version != Report::reportVersion)
            {
                throw std::logic_error("Invalid version");
            }
            bool enabled = data->at("Enabled").get<bool>();
            std::string& id = data->at("Id").get_ref<std::string&>();
            std::string& name = data->at("Name").get_ref<std::string&>();

            uint32_t reportingType = data->at("ReportingType").get<uint32_t>();
            std::vector<ReportAction> reportActions = utils::transform(
                data->at("ReportActions").get<std::vector<uint32_t>>(),
                [](const auto reportAction) {
                    return utils::toReportAction(reportAction);
                });
            uint64_t interval = data->at("Interval").get<uint64_t>();
            uint64_t appendLimit = data->at("AppendLimit").get<uint64_t>();
            uint32_t reportUpdates = data->at("ReportUpdates").get<uint32_t>();
            auto readingParameters =
                data->at("ReadingParameters")
                    .get<std::vector<LabeledMetricParameters>>();

            Readings readings = {};

            if (auto it = data->find("MetricValues"); it != data->end())
            {
                const auto labeledReadings = it->get<LabeledReadings>();
                readings = utils::toReadings(labeledReadings);
            }

            addReport(id, name, utils::toReportingType(reportingType),
                      reportActions, Milliseconds(interval), appendLimit,
                      utils::toReportUpdates(reportUpdates),
                      std::move(readingParameters), enabled,
                      std::move(readings));
        }
        catch (const std::exception& e)
        {
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "Failed to load report from storage",
                phosphor::logging::entry(
                    "FILENAME=%s",
                    static_cast<std::filesystem::path>(path).c_str()),
                phosphor::logging::entry("EXCEPTION_MSG=%s", e.what()));
            reportStorage->remove(path);
        }
    }
}
