#include "health_metric.hpp"

#include <phosphor-logging/lg2.hpp>

#include <cmath>
#include <numeric>
#include <unordered_map>

PHOSPHOR_LOG2_USING;

namespace phosphor::health::metric
{

using association_t = std::tuple<std::string, std::string, std::string>;

static constexpr double hysteresis = 1.0;

auto HealthMetric::getPath(MType type, std::string name, SubType subType)
    -> std::string
{
    std::string path;
    switch (subType)
    {
        case SubType::cpuTotal:
        {
            return std::string(BmcPath) + "/" + PathIntf::total_cpu;
        }
        case SubType::cpuKernel:
        {
            return std::string(BmcPath) + "/" + PathIntf::kernel_cpu;
        }
        case SubType::cpuUser:
        {
            return std::string(BmcPath) + "/" + PathIntf::user_cpu;
        }
        case SubType::memoryAvailable:
        {
            return std::string(BmcPath) + "/" + PathIntf::available_memory;
        }
        case SubType::memoryBufferedAndCached:
        {
            return std::string(BmcPath) + "/" +
                   PathIntf::buffered_and_cached_memory;
        }
        case SubType::memoryFree:
        {
            return std::string(BmcPath) + "/" + PathIntf::free_memory;
        }
        case SubType::memoryShared:
        {
            return std::string(BmcPath) + "/" + PathIntf::shared_memory;
        }
        case SubType::memoryTotal:
        {
            return std::string(BmcPath) + "/" + PathIntf::total_memory;
        }
        case SubType::NA:
        {
            if (type == MType::storage)
            {
                static constexpr auto nameDelimiter = "_";
                auto storageType = name.substr(
                    name.find_last_of(nameDelimiter) + 1, name.length());
                std::ranges::for_each(storageType,
                                      [](auto& c) { c = std::tolower(c); });
                return std::string(BmcPath) + "/" + PathIntf::storage + "/" +
                       storageType;
            }
            else
            {
                error("Invalid metric {SUBTYPE} for metric {TYPE}", "SUBTYPE",
                      subType, "TYPE", type);
                return "";
            }
        }
        default:
        {
            error("Invalid metric {SUBTYPE}", "SUBTYPE", subType);
            return "";
        }
    }
}

void HealthMetric::initProperties()
{
    switch (type)
    {
        case MType::cpu:
        {
            ValueIntf::unit(ValueIntf::Unit::Percent, true);
            ValueIntf::minValue(0.0, true);
            ValueIntf::maxValue(100.0, true);
            break;
        }
        case MType::memory:
        case MType::storage:
        {
            ValueIntf::unit(ValueIntf::Unit::Bytes, true);
            ValueIntf::minValue(0.0, true);
            break;
        }
        case MType::inode:
        case MType::unknown:
        default:
        {
            throw std::invalid_argument("Invalid metric type");
        }
    }
    ValueIntf::value(std::numeric_limits<double>::quiet_NaN(), true);

    using bound_map_t = std::map<Bound, double>;
    std::map<Type, bound_map_t> thresholds;
    for (const auto& [key, value] : config.thresholds)
    {
        auto type = std::get<Type>(key);
        auto bound = std::get<Bound>(key);
        auto threshold = thresholds.find(type);
        if (threshold == thresholds.end())
        {
            bound_map_t bounds;
            bounds.emplace(bound, std::numeric_limits<double>::quiet_NaN());
            thresholds.emplace(type, bounds);
        }
        else
        {
            threshold->second.emplace(bound, value.value);
        }
    }
    ThresholdIntf::value(thresholds, true);
}

bool didThresholdViolate(ThresholdIntf::Bound bound, double thresholdValue,
                         double value)
{
    switch (bound)
    {
        case ThresholdIntf::Bound::Lower:
        {
            return (value < thresholdValue);
        }
        case ThresholdIntf::Bound::Upper:
        {
            return (value > thresholdValue);
        }
        default:
        {
            error("Invalid threshold bound {BOUND}", "BOUND", bound);
            return false;
        }
    }
}

void HealthMetric::checkThreshold(Type type, Bound bound, MValue value)
{
    auto threshold = std::make_tuple(type, bound);
    auto thresholds = ThresholdIntf::value();

    if (thresholds.contains(type) && thresholds[type].contains(bound))
    {
        auto tConfig = config.thresholds.at(threshold);
        auto thresholdValue = tConfig.value / 100 * value.total;
        thresholds[type][bound] = thresholdValue;
        ThresholdIntf::value(thresholds);
        auto assertions = ThresholdIntf::asserted();
        if (didThresholdViolate(bound, thresholdValue, value.current))
        {
            if (!assertions.contains(threshold))
            {
                assertions.insert(threshold);
                ThresholdIntf::asserted(assertions);
                ThresholdIntf::assertionChanged(type, bound, true,
                                                value.current);
                if (tConfig.log)
                {
                    error(
                        "ASSERT: Health Metric {METRIC} crossed {TYPE} upper threshold",
                        "METRIC", config.name, "TYPE", type);
                    startUnit(bus, tConfig.target);
                }
            }
            return;
        }
        else if (assertions.contains(threshold))
        {
            assertions.erase(threshold);
            ThresholdIntf::asserted(assertions);
            ThresholdIntf::assertionChanged(type, bound, false, value.current);
            if (config.thresholds.find(threshold)->second.log)
            {
                info(
                    "DEASSERT: Health Metric {METRIC} is below {TYPE} upper threshold",
                    "METRIC", config.name, "TYPE", type);
            }
        }
    }
}

void HealthMetric::checkThresholds(MValue value)
{
    if (!ThresholdIntf::value().empty())
    {
        for (auto type : {Type::HardShutdown, Type::SoftShutdown,
                          Type::PerformanceLoss, Type::Critical, Type::Warning})
        {
            checkThreshold(type, Bound::Lower, value);
            checkThreshold(type, Bound::Upper, value);
        }
    }
}

auto HealthMetric::shouldNotify(MValue value) -> bool
{
    if (std::isnan(value.current))
    {
        return true;
    }
    auto changed = std::abs((value.current - lastNotifiedValue) /
                            lastNotifiedValue * 100.0);
    if (changed >= hysteresis)
    {
        lastNotifiedValue = value.current;
        return true;
    }
    return false;
}

void HealthMetric::update(MValue value)
{
    ValueIntf::value(value.current, !shouldNotify(value));

    // Maintain window size for threshold calculation
    if (history.size() >= config.windowSize)
    {
        history.pop_front();
    }
    history.push_back(value.current);

    if (history.size() < config.windowSize)
    {
        // Wait for the metric to have enough samples to calculate average
        debug("Not enough samples to calculate average");
        return;
    }

    double average = (std::accumulate(history.begin(), history.end(), 0.0)) /
                     history.size();
    value.current = average;
    checkThresholds(value);
}

void HealthMetric::create(const paths_t& bmcPaths)
{
    info("Create Health Metric: {METRIC}", "METRIC", config.name);
    initProperties();

    std::vector<association_t> associations;
    static constexpr auto forwardAssociation = "measuring";
    static constexpr auto reverseAssociation = "measured_by";
    for (const auto& bmcPath : bmcPaths)
    {
        /*
         * This metric is "measuring" the health for the BMC at bmcPath
         * The BMC at bmcPath is "measured_by" this metric.
         */
        associations.push_back(
            {forwardAssociation, reverseAssociation, bmcPath});
    }
    AssociationIntf::associations(associations);
}

} // namespace phosphor::health::metric
