#include "report.hpp"

#include "errors.hpp"
#include "messages/collect_trigger_id.hpp"
#include "messages/trigger_presence_changed_ind.hpp"
#include "messages/update_report_ind.hpp"
#include "report_manager.hpp"
#include "utils/clock.hpp"
#include "utils/contains.hpp"
#include "utils/dbus_path_utils.hpp"
#include "utils/ensure.hpp"
#include "utils/transform.hpp"

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

#include <limits>
#include <numeric>
#include <optional>

Report::Report(boost::asio::io_context& ioc,
               const std::shared_ptr<sdbusplus::asio::object_server>& objServer,
               const std::string& reportId, const std::string& reportName,
               const ReportingType reportingTypeIn,
               std::vector<ReportAction> reportActionsIn,
               const Milliseconds intervalIn, const uint64_t appendLimitIn,
               const ReportUpdates reportUpdatesIn,
               interfaces::ReportManager& reportManager,
               interfaces::JsonStorage& reportStorageIn,
               std::vector<std::shared_ptr<interfaces::Metric>> metricsIn,
               const interfaces::ReportFactory& reportFactory,
               const bool enabledIn, std::unique_ptr<interfaces::Clock> clock,
               Readings readingsIn) :
    id(reportId),
    path(utils::pathAppend(utils::constants::reportDirPath, id)),
    name(reportName), reportingType(reportingTypeIn), interval(intervalIn),
    reportActions(reportActionsIn.begin(), reportActionsIn.end()),
    metricCount(getMetricCount(metricsIn)), appendLimit(appendLimitIn),
    reportUpdates(reportUpdatesIn), readings(std::move(readingsIn)),
    readingsBuffer(std::get<1>(readings),
                   deduceBufferSize(reportUpdates, reportingType)),
    objServer(objServer), metrics(std::move(metricsIn)), timer(ioc),
    triggerIds(collectTriggerIds(ioc)), reportStorage(reportStorageIn),
    clock(std::move(clock)), messanger(ioc)
{
    readingParameters =
        toReadingParameters(utils::transform(metrics, [](const auto& metric) {
        return metric->dumpConfiguration();
    }));

    reportActions.insert(ReportAction::logToMetricReportsCollection);

    deleteIface = objServer->add_unique_interface(
        getPath(), deleteIfaceName,
        [this, &ioc, &reportManager](auto& dbusIface) {
        dbusIface.register_method("Delete", [this, &ioc, &reportManager] {
            if (persistency)
            {
                persistency = false;

                reportIface->signal_property("Persistency");
            }

            boost::asio::post(ioc, [this, &reportManager] {
                reportManager.removeReport(this);
            });
        });
    });

    auto errorMessages = verify(reportingType, interval);
    state.set<ReportFlags::enabled, ReportFlags::valid>(enabledIn,
                                                        errorMessages.empty());

    reportIface = makeReportInterface(reportFactory);
    persistency = storeConfiguration();

    messanger.on_receive<messages::TriggerPresenceChangedInd>(
        [this](const auto& msg) {
        const auto oldSize = triggerIds.size();

        if (msg.presence == messages::Presence::Exist)
        {
            if (utils::contains(msg.reportIds, id))
            {
                triggerIds.insert(msg.triggerId);
            }
            else if (!utils::contains(msg.reportIds, id))
            {
                triggerIds.erase(msg.triggerId);
            }
        }
        else if (msg.presence == messages::Presence::Removed)
        {
            triggerIds.erase(msg.triggerId);
        }

        if (triggerIds.size() != oldSize)
        {
            reportIface->signal_property("Triggers");
        }
    });

    messanger.on_receive<messages::UpdateReportInd>([this](const auto& msg) {
        if (utils::contains(msg.reportIds, id))
        {
            updateReadings();
        }
    });
}

Report::~Report()
{
    if (persistency)
    {
        if (shouldStoreMetricValues())
        {
            storeConfiguration();
        }
    }
    else
    {
        reportStorage.remove(reportFileName());
    }
}

void Report::activate()
{
    for (auto& metric : metrics)
    {
        metric->initialize();
    }

    scheduleTimer();
}

void Report::deactivate()
{
    for (auto& metric : metrics)
    {
        metric->deinitialize();
    }

    unregisterFromMetrics = nullptr;
    timer.cancel();
}

uint64_t Report::getMetricCount(
    const std::vector<std::shared_ptr<interfaces::Metric>>& metrics)
{
    uint64_t metricCount = 0;
    for (auto& metric : metrics)
    {
        metricCount += metric->metricCount();
    }
    return metricCount;
}

uint64_t Report::deduceBufferSize(const ReportUpdates reportUpdatesIn,
                                  const ReportingType reportingTypeIn) const
{
    if (reportUpdatesIn == ReportUpdates::overwrite ||
        reportingTypeIn == ReportingType::onRequest)
    {
        return metricCount;
    }
    else
    {
        return appendLimit;
    }
}

void Report::setReadingBuffer(const ReportUpdates newReportUpdates)
{
    const auto newBufferSize = deduceBufferSize(newReportUpdates,
                                                reportingType);
    if (readingsBuffer.size() != newBufferSize)
    {
        readingsBuffer.clearAndResize(newBufferSize);
    }
}

void Report::setReportUpdates(const ReportUpdates newReportUpdates)
{
    if (reportUpdates != newReportUpdates)
    {
        setReadingBuffer(newReportUpdates);
        reportUpdates = newReportUpdates;
    }
}

std::unique_ptr<sdbusplus::asio::dbus_interface>
    Report::makeReportInterface(const interfaces::ReportFactory& reportFactory)
{
    auto dbusIface = objServer->add_unique_interface(getPath(),
                                                     reportIfaceName);
    dbusIface->register_property_rw<bool>(
        "Enabled", sdbusplus::vtable::property_::emits_change,
        [this](bool newVal, auto& oldValue) {
        if (newVal != state.get<ReportFlags::enabled>())
        {
            state.set<ReportFlags::enabled>(oldValue = newVal);

            persistency = storeConfiguration();
        }
        return 1;
    },
        [this](const auto&) { return state.get<ReportFlags::enabled>(); });
    dbusIface->register_method(
        "SetReportingProperties",
        [this](std::string newReportingType, uint64_t newInterval) {
        ReportingType newReportingTypeT = reportingType;

        if (!newReportingType.empty())
        {
            newReportingTypeT = utils::toReportingType(newReportingType);
        }

        Milliseconds newIntervalT = interval;

        if (newInterval != std::numeric_limits<uint64_t>::max())
        {
            newIntervalT = Milliseconds(newInterval);
        }

        auto errorMessages = verify(newReportingTypeT, newIntervalT);

        if (!errorMessages.empty())
        {
            if (newIntervalT != interval)
            {
                throw errors::InvalidArgument("Interval");
            }

            throw errors::InvalidArgument("ReportingType");
        }

        if (reportingType != newReportingTypeT)
        {
            reportingType = newReportingTypeT;
            reportIface->signal_property("ReportingType");
        }

        if (interval != newIntervalT)
        {
            interval = newIntervalT;
            reportIface->signal_property("Interval");
        }

        if (state.set<ReportFlags::valid>(errorMessages.empty()) ==
            StateEvent::active)
        {
            scheduleTimer();
        }

        persistency = storeConfiguration();

        setReadingBuffer(reportUpdates);
    });
    dbusIface->register_property_r<uint64_t>(
        "Interval", sdbusplus::vtable::property_::emits_change,
        [this](const auto&) { return interval.count(); });
    dbusIface->register_property_rw<bool>(
        "Persistency", sdbusplus::vtable::property_::emits_change,
        [this](bool newVal, auto& oldVal) {
        if (newVal == persistency)
        {
            return 1;
        }
        if (newVal)
        {
            persistency = oldVal = storeConfiguration();
        }
        else
        {
            reportStorage.remove(reportFileName());
            persistency = oldVal = false;
        }
        return 1;
    },
        [this](const auto&) { return persistency; });

    dbusIface->register_property_r("Readings", readings,
                                   sdbusplus::vtable::property_::emits_change,
                                   [this](const auto&) { return readings; });
    dbusIface->register_property_r<std::string>(
        "ReportingType", sdbusplus::vtable::property_::emits_change,
        [this](const auto&) { return utils::enumToString(reportingType); });
    dbusIface->register_property_rw(
        "ReadingParameters", readingParameters,
        sdbusplus::vtable::property_::emits_change,
        [this, &reportFactory](auto newVal, auto& oldVal) {
        auto labeledMetricParams = reportFactory.convertMetricParams(newVal);
        reportFactory.updateMetrics(metrics, state.get<ReportFlags::enabled>(),
                                    labeledMetricParams);
        readingParameters = toReadingParameters(
            utils::transform(metrics, [](const auto& metric) {
            return metric->dumpConfiguration();
        }));
        metricCount = getMetricCount(metrics);
        setReadingBuffer(reportUpdates);
        persistency = storeConfiguration();
        oldVal = std::move(newVal);
        return 1;
    },
        [this](const auto&) { return readingParameters; });
    dbusIface->register_property_r<bool>("EmitsReadingsUpdate",
                                         sdbusplus::vtable::property_::none,
                                         [this](const auto&) {
        return reportActions.contains(ReportAction::emitsReadingsUpdate);
    });
    dbusIface->register_property_r<std::string>(
        "Name", sdbusplus::vtable::property_::const_,
        [this](const auto&) { return name; });
    dbusIface->register_property_r<bool>("LogToMetricReportsCollection",
                                         sdbusplus::vtable::property_::const_,
                                         [this](const auto&) {
        return reportActions.contains(
            ReportAction::logToMetricReportsCollection);
    });
    dbusIface->register_property_rw<std::vector<std::string>>(
        "ReportActions", sdbusplus::vtable::property_::emits_change,
        [this](auto newVal, auto& oldVal) {
        auto tmp = utils::transform<std::unordered_set>(
            newVal, [](const auto& reportAction) {
            return utils::toReportAction(reportAction);
        });
        tmp.insert(ReportAction::logToMetricReportsCollection);

        if (tmp != reportActions)
        {
            reportActions = tmp;
            persistency = storeConfiguration();
            oldVal = std::move(newVal);
        }
        return 1;
    },
        [this](const auto&) {
        return utils::transform<std::vector>(reportActions,
                                             [](const auto reportAction) {
            return utils::enumToString(reportAction);
        });
    });
    dbusIface->register_property_r<uint64_t>(
        "AppendLimit", sdbusplus::vtable::property_::emits_change,
        [this](const auto&) { return appendLimit; });
    dbusIface->register_property_rw(
        "ReportUpdates", std::string(),
        sdbusplus::vtable::property_::emits_change,
        [this](auto newVal, auto& oldVal) {
        setReportUpdates(utils::toReportUpdates(newVal));
        oldVal = newVal;
        return 1;
    },
        [this](const auto&) { return utils::enumToString(reportUpdates); });
    dbusIface->register_property_r(
        "Triggers", std::vector<sdbusplus::message::object_path>{},
        sdbusplus::vtable::property_::emits_change, [this](const auto&) {
        return utils::transform<std::vector>(triggerIds,
                                             [](const auto& triggerId) {
            return utils::pathAppend(utils::constants::triggerDirPath,
                                     triggerId);
        });
    });
    dbusIface->register_method("Update", [this] {
        if (reportingType == ReportingType::onRequest)
        {
            updateReadings();
        }
    });
    constexpr bool skipPropertiesChangedSignal = true;
    dbusIface->initialize(skipPropertiesChangedSignal);
    return dbusIface;
}

void Report::timerProcForPeriodicReport(boost::system::error_code ec,
                                        Report& self)
{
    if (ec)
    {
        return;
    }

    self.updateReadings();
    self.scheduleTimerForPeriodicReport(self.interval);
}

void Report::timerProcForOnChangeReport(boost::system::error_code ec,
                                        Report& self)
{
    if (ec)
    {
        return;
    }

    const auto ensure =
        utils::Ensure{[&self] { self.onChangeContext = std::nullopt; }};

    self.onChangeContext.emplace(self);

    const auto steadyTimestamp = self.clock->steadyTimestamp();

    for (auto& metric : self.metrics)
    {
        metric->updateReadings(steadyTimestamp);
    }

    self.scheduleTimerForOnChangeReport();
}

void Report::scheduleTimerForPeriodicReport(Milliseconds timerInterval)
{
    try
    {
        timer.expires_after(timerInterval);
        timer.async_wait([this](boost::system::error_code ec) {
            timerProcForPeriodicReport(ec, *this);
        });
    }
    catch (const boost::system::system_error& exception)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "Failed to schedule timer for periodic report: ",
            phosphor::logging::entry("EXCEPTION_MSG=%s", exception.what()));
    }
}

void Report::scheduleTimerForOnChangeReport()
{
    constexpr Milliseconds timerInterval{100};

    timer.expires_after(timerInterval);
    timer.async_wait([this](boost::system::error_code ec) {
        timerProcForOnChangeReport(ec, *this);
    });
}

void Report::updateReadings()
{
    if (!state.isActive())
    {
        return;
    }

    if (reportUpdates == ReportUpdates::overwrite ||
        reportingType == ReportingType::onRequest)
    {
        readingsBuffer.clear();
    }

    for (const auto& metric : metrics)
    {
        if (!state.isActive())
        {
            break;
        }

        for (const auto& [metadata, value, timestamp] :
             metric->getUpdatedReadings())
        {
            if (reportUpdates == ReportUpdates::appendStopsWhenFull &&
                readingsBuffer.isFull())
            {
                state.set<ReportFlags::enabled>(false);
                reportIface->signal_property("Enabled");
                break;
            }
            readingsBuffer.emplace(metadata, value, timestamp);
        }
    }

    std::get<0>(readings) =
        std::chrono::duration_cast<Milliseconds>(clock->systemTimestamp())
            .count();

    if (utils::contains(reportActions, ReportAction::emitsReadingsUpdate))
    {
        reportIface->signal_property("Readings");
    }
}

bool Report::shouldStoreMetricValues() const
{
    return reportingType != ReportingType::onRequest &&
           reportUpdates == ReportUpdates::appendStopsWhenFull;
}

bool Report::storeConfiguration() const
{
    try
    {
        nlohmann::json data;

        data["Enabled"] = state.get<ReportFlags::enabled>();
        data["Version"] = reportVersion;
        data["Id"] = id;
        data["Name"] = name;
        data["ReportingType"] = utils::toUnderlying(reportingType);
        data["ReportActions"] = utils::transform(reportActions,
                                                 [](const auto reportAction) {
            return utils::toUnderlying(reportAction);
        });
        data["Interval"] = interval.count();
        data["AppendLimit"] = appendLimit;
        data["ReportUpdates"] = utils::toUnderlying(reportUpdates);
        data["ReadingParameters"] = utils::transform(
            metrics,
            [](const auto& metric) { return metric->dumpConfiguration(); });

        if (shouldStoreMetricValues())
        {
            data["MetricValues"] = utils::toLabeledReadings(readings);
        }

        reportStorage.store(reportFileName(), data);
    }
    catch (const std::exception& e)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "Failed to store a report in storage",
            phosphor::logging::entry("EXCEPTION_MSG=%s", e.what()));
        return false;
    }

    return true;
}

interfaces::JsonStorage::FilePath Report::reportFileName() const
{
    return interfaces::JsonStorage::FilePath{
        std::to_string(std::hash<std::string>{}(id))};
}

std::unordered_set<std::string>
    Report::collectTriggerIds(boost::asio::io_context& ioc) const
{
    utils::Messanger tmp(ioc);

    auto result = std::unordered_set<std::string>();

    tmp.on_receive<messages::CollectTriggerIdResp>(
        [&result](const auto& msg) { result.insert(msg.triggerId); });

    tmp.send(messages::CollectTriggerIdReq{id});

    return result;
}

void Report::metricUpdated()
{
    if (onChangeContext)
    {
        onChangeContext->metricUpdated();
        return;
    }

    updateReadings();
}

void Report::scheduleTimer()
{
    switch (reportingType)
    {
        case ReportingType::periodic:
        {
            unregisterFromMetrics = nullptr;
            scheduleTimerForPeriodicReport(interval);
            break;
        }
        case ReportingType::onChange:
        {
            if (!unregisterFromMetrics)
            {
                unregisterFromMetrics = [this] {
                    for (auto& metric : metrics)
                    {
                        metric->unregisterFromUpdates(*this);
                    }
                };

                for (auto& metric : metrics)
                {
                    metric->registerForUpdates(*this);
                }
            }

            bool isTimerRequired = false;

            for (auto& metric : metrics)
            {
                if (metric->isTimerRequired())
                {
                    isTimerRequired = true;
                }
            }

            if (isTimerRequired)
            {
                scheduleTimerForOnChangeReport();
            }
            else
            {
                timer.cancel();
            }
            break;
        }
        default:
            unregisterFromMetrics = nullptr;
            timer.cancel();
            break;
    }
}

std::vector<ErrorMessage> Report::verify(ReportingType reportingType,
                                         Milliseconds interval)
{
    if (interval != Milliseconds{0} && interval < ReportManager::minInterval)
    {
        throw errors::InvalidArgument("Interval");
    }

    std::vector<ErrorMessage> result;

    if ((reportingType == ReportingType::periodic &&
         interval == Milliseconds{0}) ||
        (reportingType != ReportingType::periodic &&
         interval != Milliseconds{0}))
    {
        result.emplace_back(ErrorType::propertyConflict, "Interval");
        result.emplace_back(ErrorType::propertyConflict, "ReportingType");
    }

    return result;
}
