#include "mctp_endpoint_discovery.hpp"

#include "common/types.hpp"
#include "common/utils.hpp"

#include <linux/mctp.h>

#include <phosphor-logging/lg2.hpp>

#include <algorithm>
#include <map>
#include <string>
#include <string_view>
#include <vector>

using namespace sdbusplus::bus::match::rules;

PHOSPHOR_LOG2_USING;

namespace pldm
{
MctpDiscovery::MctpDiscovery(
    sdbusplus::bus_t& bus,
    std::initializer_list<MctpDiscoveryHandlerIntf*> list) :
    bus(bus),
    mctpEndpointAddedSignal(
        bus, interfacesAdded(MCTPPath),
        [this](sdbusplus::message_t& msg) { this->discoverEndpoints(msg); }),
    mctpEndpointRemovedSignal(
        bus, interfacesRemoved(MCTPPath),
        [this](sdbusplus::message_t& msg) { this->removeEndpoints(msg); }),
    mctpEndpointPropChangedSignal(
        bus, propertiesChangedNamespace(MCTPPath, MCTPInterfaceCC),
        [this](sdbusplus::message_t& msg) { this->propertiesChangedCb(msg); }),
    handlers(list)
{
    std::map<MctpInfo, Availability> currentMctpInfoMap;
    getMctpInfos(currentMctpInfoMap);
    for (const auto& mapIt : currentMctpInfoMap)
    {
        if (mapIt.second)
        {
            // Only add the available endpoints to the terminus
            // Let the propertiesChanged signal tells us when it comes back
            // to Available again
            addToExistingMctpInfos(MctpInfos(1, mapIt.first));
        }
    }
    handleMctpEndpoints(existingMctpInfos);
}

void MctpDiscovery::getMctpInfos(std::map<MctpInfo, Availability>& mctpInfoMap)
{
    // Find all implementations of the MCTP Endpoint interface
    pldm::utils::GetSubTreeResponse mapperResponse;
    try
    {
        mapperResponse = pldm::utils::DBusHandler().getSubtree(
            MCTPPath, 0, std::vector<std::string>({MCTPEndpoint::interface}));
    }
    catch (const sdbusplus::exception_t& e)
    {
        error(
            "Failed to getSubtree call at path '{PATH}' and interface '{INTERFACE}', error - {ERROR} ",
            "ERROR", e, "PATH", MCTPPath, "INTERFACE", MCTPEndpoint::interface);
        return;
    }

    for (const auto& [path, services] : mapperResponse)
    {
        for (const auto& serviceIter : services)
        {
            const std::string& service = serviceIter.first;
            const MctpEndpointProps& epProps =
                getMctpEndpointProps(service, path);
            const UUID& uuid = getEndpointUUIDProp(service, path);
            const Availability& availability =
                getEndpointConnectivityProp(path);
            auto types = std::get<MCTPMsgTypes>(epProps);
            if (std::find(types.begin(), types.end(), mctpTypePLDM) !=
                types.end())
            {
                auto mctpInfo =
                    MctpInfo(std::get<eid>(epProps), uuid, "",
                             std::get<NetworkId>(epProps), std::nullopt);
                searchConfigurationFor(pldm::utils::DBusHandler(), mctpInfo);
                mctpInfoMap[std::move(mctpInfo)] = availability;
            }
        }
    }
}

MctpEndpointProps MctpDiscovery::getMctpEndpointProps(
    const std::string& service, const std::string& path)
{
    try
    {
        auto properties = pldm::utils::DBusHandler().getDbusPropertiesVariant(
            service.c_str(), path.c_str(), MCTPEndpoint::interface);

        if (properties.contains(MCTPEndpoint::property_names::network_id) &&
            properties.contains(MCTPEndpoint::property_names::eid) &&
            properties.contains(
                MCTPEndpoint::property_names::supported_message_types))
        {
            auto networkId = std::get<NetworkId>(
                properties.at(MCTPEndpoint::property_names::network_id));
            auto eid = std::get<mctp_eid_t>(
                properties.at(MCTPEndpoint::property_names::eid));
            auto types = std::get<std::vector<uint8_t>>(properties.at(
                MCTPEndpoint::property_names::supported_message_types));
            return MctpEndpointProps(networkId, eid, types);
        }
    }
    catch (const sdbusplus::exception_t& e)
    {
        error(
            "Error reading MCTP Endpoint property at path '{PATH}' and service '{SERVICE}', error - {ERROR}",
            "SERVICE", service, "PATH", path, "ERROR", e);
        return MctpEndpointProps(0, MCTP_ADDR_ANY, {});
    }

    return MctpEndpointProps(0, MCTP_ADDR_ANY, {});
}

UUID MctpDiscovery::getEndpointUUIDProp(const std::string& service,
                                        const std::string& path)
{
    try
    {
        auto properties = pldm::utils::DBusHandler().getDbusPropertiesVariant(
            service.c_str(), path.c_str(), CommonUUID::interface);

        if (properties.contains("UUID"))
        {
            return std::get<UUID>(properties.at("UUID"));
        }
    }
    catch (const sdbusplus::exception_t& e)
    {
        error(
            "Error reading Endpoint UUID property at path '{PATH}' and service '{SERVICE}', error - {ERROR}",
            "SERVICE", service, "PATH", path, "ERROR", e);
        return static_cast<UUID>(emptyUUID);
    }

    return static_cast<UUID>(emptyUUID);
}

Availability MctpDiscovery::getEndpointConnectivityProp(const std::string& path)
{
    Availability available = false;
    try
    {
        pldm::utils::PropertyValue propertyValue =
            pldm::utils::DBusHandler().getDbusPropertyVariant(
                path.c_str(), MCTPConnectivityProp, MCTPInterfaceCC);
        if (std::get<std::string>(propertyValue) == "Available")
        {
            available = true;
        }
    }
    catch (const sdbusplus::exception_t& e)
    {
        error(
            "Error reading Endpoint Connectivity property at path '{PATH}', error - {ERROR}",
            "PATH", path, "ERROR", e);
    }

    return available;
}

void MctpDiscovery::getAddedMctpInfos(sdbusplus::message_t& msg,
                                      MctpInfos& mctpInfos)
{
    using ObjectPath = sdbusplus::object_path;
    ObjectPath objPath;
    using Property = std::string;
    using PropertyMap = std::map<Property, dbus::Value>;
    std::map<std::string, PropertyMap> interfaces;
    std::string uuid = emptyUUID;

    try
    {
        msg.read(objPath, interfaces);
    }
    catch (const sdbusplus::exception_t& e)
    {
        error(
            "Error reading MCTP Endpoint added interface message, error - {ERROR}",
            "ERROR", e);
        return;
    }
    Availability availability = getEndpointConnectivityProp(objPath.str);

    /* Get UUID */
    try
    {
        auto service = pldm::utils::DBusHandler().getService(
            objPath.str.c_str(), CommonUUID::interface);
        uuid = getEndpointUUIDProp(service, objPath.str);
    }
    catch (const sdbusplus::exception_t& e)
    {
        error("Error getting Endpoint UUID D-Bus interface, error - {ERROR}",
              "ERROR", e);
    }

    for (const auto& [intfName, properties] : interfaces)
    {
        if (intfName == MCTPEndpoint::interface)
        {
            if (properties.contains(MCTPEndpoint::property_names::network_id) &&
                properties.contains(MCTPEndpoint::property_names::eid) &&
                properties.contains(
                    MCTPEndpoint::property_names::supported_message_types))
            {
                auto networkId = std::get<NetworkId>(
                    properties.at(MCTPEndpoint::property_names::network_id));
                auto eid = std::get<mctp_eid_t>(
                    properties.at(MCTPEndpoint::property_names::eid));
                auto types = std::get<std::vector<uint8_t>>(properties.at(
                    MCTPEndpoint::property_names::supported_message_types));

                if (!availability)
                {
                    // Log an error message here, but still add it to the
                    // terminus
                    error(
                        "mctpd added a DEGRADED endpoint {EID} networkId {NET} to D-Bus",
                        "NET", networkId, "EID", static_cast<unsigned>(eid));
                }
                if (std::find(types.begin(), types.end(), mctpTypePLDM) !=
                    types.end())
                {
                    info(
                        "Adding Endpoint networkId '{NETWORK}' and EID '{EID}' UUID '{UUID}'",
                        "NETWORK", networkId, "EID", eid, "UUID", uuid);
                    auto mctpInfo =
                        MctpInfo(eid, uuid, "", networkId, std::nullopt);
                    searchConfigurationFor(pldm::utils::DBusHandler(),
                                           mctpInfo);
                    mctpInfos.emplace_back(std::move(mctpInfo));
                }
            }
        }
    }
}

void MctpDiscovery::addToExistingMctpInfos(const MctpInfos& addedInfos)
{
    for (const auto& mctpInfo : addedInfos)
    {
        if (std::find(existingMctpInfos.begin(), existingMctpInfos.end(),
                      mctpInfo) == existingMctpInfos.end())
        {
            existingMctpInfos.emplace_back(mctpInfo);
        }
    }
}

void MctpDiscovery::removeFromExistingMctpInfos(MctpInfos& mctpInfos,
                                                MctpInfos& removedInfos)
{
    for (const auto& mctpInfo : existingMctpInfos)
    {
        if (std::find(mctpInfos.begin(), mctpInfos.end(), mctpInfo) ==
            mctpInfos.end())
        {
            removedInfos.emplace_back(mctpInfo);
        }
    }
    for (const auto& mctpInfo : removedInfos)
    {
        info("Removing Endpoint networkId '{NETWORK}' and  EID '{EID}'",
             "NETWORK", std::get<3>(mctpInfo), "EID", std::get<0>(mctpInfo));
        existingMctpInfos.erase(std::remove(existingMctpInfos.begin(),
                                            existingMctpInfos.end(), mctpInfo),
                                existingMctpInfos.end());
    }
}

void MctpDiscovery::propertiesChangedCb(sdbusplus::message_t& msg)
{
    using Interface = std::string;
    using Property = std::string;
    using Value = std::string;
    using Properties = std::map<Property, std::variant<Value>>;

    Interface interface;
    Properties properties;
    std::string objPath{};
    std::string service{};

    try
    {
        msg.read(interface, properties);
        objPath = msg.get_path();
    }
    catch (const sdbusplus::exception_t& e)
    {
        error(
            "Error handling Connectivity property changed message, error - {ERROR}",
            "ERROR", e);
        return;
    }

    for (const auto& [key, valueVariant] : properties)
    {
        Value propVal = std::get<std::string>(valueVariant);
        auto availability = (propVal == "Available") ? true : false;

        if (key == MCTPConnectivityProp)
        {
            try
            {
                service = pldm::utils::DBusHandler().getService(
                    objPath.c_str(), MCTPEndpoint::interface);
            }
            catch (const sdbusplus::exception_t& e)
            {
                error(
                    "Error getting service for path '{PATH}', error - {ERROR}",
                    "PATH", objPath, "ERROR", e);
                return;
            }
            const MctpEndpointProps& epProps =
                getMctpEndpointProps(service, objPath);

            auto types = std::get<MCTPMsgTypes>(epProps);
            if (!std::ranges::contains(types, mctpTypePLDM))
            {
                return;
            }
            const UUID& uuid = getEndpointUUIDProp(service, objPath);

            MctpInfo mctpInfo(std::get<eid>(epProps), uuid, "",
                              std::get<NetworkId>(epProps), std::nullopt);
            searchConfigurationFor(pldm::utils::DBusHandler(), mctpInfo);
            if (!std::ranges::contains(existingMctpInfos, mctpInfo))
            {
                if (availability)
                {
                    // The endpoint not in existingMctpInfos and is
                    // available Add it to existingMctpInfos
                    info(
                        "Adding Endpoint networkId {NETWORK} ID {EID} by propertiesChanged signal",
                        "NETWORK", std::get<3>(mctpInfo), "EID",
                        unsigned(std::get<0>(mctpInfo)));
                    addToExistingMctpInfos(MctpInfos(1, mctpInfo));
                    handleMctpEndpoints(MctpInfos(1, mctpInfo));
                }
            }
            else
            {
                // The endpoint already in existingMctpInfos
                updateMctpEndpointAvailability(mctpInfo, availability);
            }
        }
    }
}

void MctpDiscovery::discoverEndpoints(sdbusplus::message_t& msg)
{
    MctpInfos addedInfos;
    getAddedMctpInfos(msg, addedInfos);
    addToExistingMctpInfos(addedInfos);
    handleMctpEndpoints(addedInfos);
}

void MctpDiscovery::removeEndpoints(sdbusplus::message_t&)
{
    MctpInfos mctpInfos;
    MctpInfos removedInfos;
    std::map<MctpInfo, Availability> currentMctpInfoMap;
    getMctpInfos(currentMctpInfoMap);
    for (const auto& mapIt : currentMctpInfoMap)
    {
        mctpInfos.push_back(mapIt.first);
    }
    removeFromExistingMctpInfos(mctpInfos, removedInfos);
    handleRemovedMctpEndpoints(removedInfos);
    removeConfigs(removedInfos);
}

void MctpDiscovery::handleMctpEndpoints(const MctpInfos& mctpInfos)
{
    for (const auto& handler : handlers)
    {
        if (handler)
        {
            handler->handleConfigurations(configurations);
            handler->handleMctpEndpoints(mctpInfos);
        }
    }
}

void MctpDiscovery::handleRemovedMctpEndpoints(const MctpInfos& mctpInfos)
{
    for (const auto& handler : handlers)
    {
        if (handler)
        {
            handler->handleRemovedMctpEndpoints(mctpInfos);
        }
    }
}

void MctpDiscovery::updateMctpEndpointAvailability(const MctpInfo& mctpInfo,
                                                   Availability availability)
{
    for (const auto& handler : handlers)
    {
        if (handler)
        {
            handler->updateMctpEndpointAvailability(mctpInfo, availability);
        }
    }
}

std::string MctpDiscovery::getNameFromProperties(
    const utils::PropertyMap& properties)
{
    if (!properties.contains("Name"))
    {
        error("Missing name property");
        return "";
    }
    return std::get<std::string>(properties.at("Name"));
}

std::string MctpDiscovery::constructMctpReactorObjectPath(
    const MctpInfo& mctpInfo)
{
    const auto networkId = std::get<NetworkId>(mctpInfo);
    const auto eid = std::get<pldm::eid>(mctpInfo);
    return std::string{MCTPPath} + "/networks/" + std::to_string(networkId) +
           "/endpoints/" + std::to_string(eid) + "/configured_by";
}

void MctpDiscovery::searchConfigurationFor(
    const pldm::utils::DBusHandler& handler, MctpInfo& mctpInfo)
{
    const auto mctpReactorObjectPath = constructMctpReactorObjectPath(mctpInfo);
    try
    {
        std::string associatedObjPath;
        std::string associatedService;
        std::string associatedInterface;
        sdbusplus::object_path inventorySubtreePath(inventorySubtreePathStr);

        //"/{board or chassis type}/{board or chassis}/{device}"
        auto constexpr subTreeDepth = 3;
        auto response = handler.getAssociatedSubTree(
            mctpReactorObjectPath, inventorySubtreePath, subTreeDepth,
            interfaceFilter);
        if (response.empty())
        {
            warning("No associated subtree found for path {PATH}", "PATH",
                    mctpReactorObjectPath);
            return;
        }
        // Assume the first entry is the one we want
        auto subTree = response.begin();
        associatedObjPath = subTree->first;
        auto associatedServiceProp = subTree->second;
        if (associatedServiceProp.empty())
        {
            warning("No associated service found for path {PATH}", "PATH",
                    mctpReactorObjectPath);
            return;
        }
        // Assume the first entry is the one we want
        auto entry = associatedServiceProp.begin();
        associatedService = entry->first;
        auto dBusIntfList = entry->second;
        auto associatedInterfaceItr = std::find_if(
            dBusIntfList.begin(), dBusIntfList.end(), [](const auto& intf) {
                return std::find(interfaceFilter.begin(), interfaceFilter.end(),
                                 intf) != interfaceFilter.end();
            });
        if (associatedInterfaceItr == dBusIntfList.end())
        {
            error("No associated interface found for path {PATH}", "PATH",
                  mctpReactorObjectPath);
            return;
        }
        associatedInterface = *associatedInterfaceItr;
        auto mctpTargetProperties = handler.getDbusPropertiesVariant(
            associatedService.c_str(), associatedObjPath.c_str(),
            associatedInterface.c_str());
        auto name = getNameFromProperties(mctpTargetProperties);
        if (!name.empty())
        {
            std::get<std::optional<std::string>>(mctpInfo) = name;
        }
        configurations.emplace(associatedObjPath, mctpInfo);
    }
    catch (const std::exception& e)
    {
        error(
            "Error getting associated subtree for path {PATH}, error - {ERROR}",
            "PATH", mctpReactorObjectPath, "ERROR", e);
        return;
    }
}

void MctpDiscovery::removeConfigs(const MctpInfos& removedInfos)
{
    for (const auto& mctpInfo : removedInfos)
    {
        const auto eidToRemove = std::get<eid>(mctpInfo);
        const auto netToRemove = std::get<NetworkId>(mctpInfo);

        std::erase_if(configurations, [eidToRemove,
                                       netToRemove](const auto& config) {
            const auto& [__, mctpInfo] = config;
            const auto eidValue = std::get<eid>(mctpInfo);
            const auto netValue = std::get<NetworkId>(mctpInfo);

            return eidValue == eidToRemove && netValue == netToRemove;
        });
    }
}

} // namespace pldm
