#include "system_queries.hpp"

#include "netlink.hpp"
#include "rtnetlink.hpp"

#include <fmt/format.h>
#include <linux/ethtool.h>
#include <linux/sockios.h>
#include <net/if.h>

#include <algorithm>
#include <optional>
#include <phosphor-logging/log.hpp>
#include <stdexcept>
#include <stdplus/fd/create.hpp>
#include <stdplus/raw.hpp>
#include <stdplus/util/cexec.hpp>
#include <string_view>
#include <system_error>

namespace phosphor::network::system
{

using std::literals::string_view_literals::operator""sv;
using phosphor::logging::entry;
using phosphor::logging::level;
using phosphor::logging::log;

static stdplus::Fd& getIFSock()
{
    using namespace stdplus::fd;
    static auto fd =
        socket(SocketDomain::INet, SocketType::Datagram, SocketProto::IP);
    return fd;
}

static ifreq makeIFReq(std::string_view ifname)
{
    ifreq ifr = {};
    const auto copied = std::min<std::size_t>(ifname.size(), IFNAMSIZ - 1);
    std::copy_n(ifname.begin(), copied, ifr.ifr_name);
    return ifr;
}

static ifreq executeIFReq(std::string_view ifname, unsigned long cmd,
                          void* data = nullptr)
{
    ifreq ifr = makeIFReq(ifname);
    ifr.ifr_data = reinterpret_cast<char*>(data);
    getIFSock().ioctl(cmd, &ifr);
    return ifr;
}

inline auto optionalIFReq(stdplus::zstring_view ifname, unsigned long long cmd,
                          std::string_view cmdname, auto&& complete,
                          void* data = nullptr)
{
    ifreq ifr;
    std::optional<decltype(complete(ifr))> ret;
    auto ukey = std::make_tuple(std::string(ifname), cmd);
    static std::unordered_set<std::tuple<std::string, unsigned long long>>
        unsupported;
    try
    {
        ifr = executeIFReq(ifname, cmd, data);
    }
    catch (const std::system_error& e)
    {
        if (e.code() == std::errc::operation_not_supported)
        {
            if (unsupported.find(ukey) == unsupported.end())
            {
                unsupported.emplace(std::move(ukey));
                auto msg =
                    fmt::format("{} not supported on {}", cmdname, ifname);
                log<level::INFO>(msg.c_str(),
                                 entry("INTERFACE=%s", ifname.c_str()));
            }
            return ret;
        }
        throw;
    }
    unsupported.erase(ukey);
    ret.emplace(complete(ifr));
    return ret;
}

EthInfo getEthInfo(stdplus::zstring_view ifname)
{
    ethtool_cmd edata = {};
    edata.cmd = ETHTOOL_GSET;
    return optionalIFReq(
               ifname, SIOCETHTOOL, "ETHTOOL"sv,
               [&](const ifreq&) {
                   return EthInfo{.autoneg = edata.autoneg != 0,
                                  .speed = edata.speed};
               },
               &edata)
        .value_or(EthInfo{});
}

bool intfIsRunning(std::string_view ifname)
{
    return executeIFReq(ifname, SIOCGIFFLAGS).ifr_flags & IFF_RUNNING;
}

std::optional<unsigned> getMTU(stdplus::zstring_view ifname)
{
    return optionalIFReq(ifname, SIOCGIFMTU, "GMTU",
                         [](const ifreq& ifr) { return ifr.ifr_mtu; });
}

void setMTU(std::string_view ifname, unsigned mtu)
{
    auto ifr = makeIFReq(ifname);
    ifr.ifr_mtu = mtu;
    getIFSock().ioctl(SIOCSIFMTU, &ifr);
}

void setNICUp(std::string_view ifname, bool up)
{
    ifreq ifr = executeIFReq(ifname, SIOCGIFFLAGS);
    ifr.ifr_flags &= ~IFF_UP;
    ifr.ifr_flags |= up ? IFF_UP : 0;
    getIFSock().ioctl(SIOCSIFFLAGS, &ifr);
}

bool detail::validateNewAddr(const AddressInfo& info,
                             const AddressFilter& filter) noexcept
{
    if (filter.ifidx != 0 && filter.ifidx != info.ifidx)
    {
        return false;
    }
    return true;
}

bool detail::validateNewNeigh(const NeighborInfo& info,
                              const NeighborFilter& filter) noexcept
{
    if (filter.ifidx != 0 && filter.ifidx != info.ifidx)
    {
        return false;
    }
    return true;
}

std::vector<InterfaceInfo> getInterfaces()
{
    std::vector<InterfaceInfo> ret;
    auto cb = [&](const nlmsghdr&, std::string_view msg) {
        try
        {
            ret.emplace_back(netlink::intfFromRtm(msg));
        }
        catch (const std::exception& e)
        {
            auto msg = fmt::format("Failed parsing interface: {}", e.what());
            log<level::ERR>(msg.c_str());
        }
    };
    ifinfomsg msg{};
    netlink::performRequest(NETLINK_ROUTE, RTM_GETLINK, NLM_F_DUMP, msg, cb);
    return ret;
}

std::vector<AddressInfo> getAddresses(const AddressFilter& filter)
{
    std::vector<AddressInfo> ret;
    auto cb = [&](const nlmsghdr&, std::string_view msg) {
        try
        {
            auto info = netlink::addrFromRtm(msg);
            if (detail::validateNewAddr(info, filter))
            {
                ret.emplace_back(std::move(info));
            }
        }
        catch (const std::exception& e)
        {
            auto msg = fmt::format("Failed parsing address for ifidx {}: {}",
                                   filter.ifidx, e.what());
            log<level::ERR>(msg.c_str());
        }
    };
    ifaddrmsg msg{};
    msg.ifa_index = filter.ifidx;
    netlink::performRequest(NETLINK_ROUTE, RTM_GETADDR, NLM_F_DUMP, msg, cb);
    return ret;
}

std::vector<NeighborInfo> getNeighbors(const NeighborFilter& filter)
{
    std::vector<NeighborInfo> ret;
    auto cb = [&](const nlmsghdr&, std::string_view msg) {
        try
        {
            auto info = netlink::neighFromRtm(msg);
            if (detail::validateNewNeigh(info, filter))
            {
                ret.push_back(std::move(info));
            }
        }
        catch (const std::exception& e)
        {
            auto msg = fmt::format("Failed parsing neighbor for ifidx {}: {}",
                                   filter.ifidx, e.what());
            log<level::ERR>(msg.c_str());
        }
    };
    ndmsg msg{};
    msg.ndm_ifindex = filter.ifidx;
    netlink::performRequest(NETLINK_ROUTE, RTM_GETNEIGH, NLM_F_DUMP, msg, cb);
    return ret;
}

} // namespace phosphor::network::system
