#include "mock_syscall.hpp"

#include "util.hpp"

#include <arpa/inet.h>
#include <dlfcn.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>

#include <cstdarg>
#include <cstdio>
#include <cstring>
#include <map>
#include <queue>
#include <stdexcept>
#include <stdplus/raw.hpp>
#include <string>
#include <string_view>
#include <vector>

std::map<int, std::queue<std::string>> mock_rtnetlinks;

using phosphor::network::InterfaceInfo;

std::map<std::string, InterfaceInfo> mock_if;

void phosphor::network::system::mock_clear()
{
    mock_rtnetlinks.clear();
    mock_if.clear();
}

void phosphor::network::system::mock_addIF(const InterfaceInfo& info)
{
    if (info.idx == 0)
    {
        throw std::invalid_argument("Bad interface index");
    }
    for (const auto& [_, iinfo] : mock_if)
    {
        if (iinfo.idx == info.idx || iinfo.name == info.name)
        {
            throw std::invalid_argument("Interface already exists");
        }
    }
    mock_if.emplace(info.name.value(), info);
}

void validateMsgHdr(const struct msghdr* msg)
{
    if (msg->msg_namelen != sizeof(sockaddr_nl))
    {
        fprintf(stderr, "bad namelen: %u\n", msg->msg_namelen);
        abort();
    }
    const auto& from = *reinterpret_cast<sockaddr_nl*>(msg->msg_name);
    if (from.nl_family != AF_NETLINK)
    {
        fprintf(stderr, "recvmsg bad family data\n");
        abort();
    }
    if (msg->msg_iovlen != 1)
    {
        fprintf(stderr, "recvmsg unsupported iov configuration\n");
        abort();
    }
}

void appendRTAttr(std::string& msgBuf, unsigned short type,
                  std::string_view data)
{
    const auto rta_begin = msgBuf.size();
    msgBuf.append(RTA_SPACE(data.size()), '\0');
    auto& rta = *reinterpret_cast<rtattr*>(msgBuf.data() + rta_begin);
    rta.rta_len = RTA_LENGTH(data.size());
    rta.rta_type = type;
    std::copy(data.begin(), data.end(),
              msgBuf.data() + rta_begin + RTA_LENGTH(0));
}

ssize_t sendmsg_link_dump(std::queue<std::string>& msgs, std::string_view in)
{
    if (const auto& hdrin = *reinterpret_cast<const nlmsghdr*>(in.data());
        hdrin.nlmsg_type != RTM_GETLINK)
    {
        return 0;
    }

    std::string msgBuf;
    msgBuf.reserve(8192);
    for (const auto& [name, i] : mock_if)
    {
        if (msgBuf.size() > 4096)
        {
            msgs.emplace(std::move(msgBuf));
        }
        const auto nlbegin = msgBuf.size();
        msgBuf.append(NLMSG_SPACE(sizeof(ifinfomsg)), '\0');
        {
            auto& info = *reinterpret_cast<ifinfomsg*>(msgBuf.data() + nlbegin +
                                                       NLMSG_HDRLEN);
            info.ifi_index = i.idx;
            info.ifi_flags = i.flags;
        }
        if (i.name)
        {
            appendRTAttr(msgBuf, IFLA_IFNAME, {name.data(), name.size() + 1});
        }
        if (i.mac)
        {
            appendRTAttr(msgBuf, IFLA_ADDRESS,
                         stdplus::raw::asView<char>(*i.mac));
        }
        if (i.mtu)
        {
            appendRTAttr(msgBuf, IFLA_MTU, stdplus::raw::asView<char>(*i.mtu));
        }
        auto& hdr = *reinterpret_cast<nlmsghdr*>(msgBuf.data() + nlbegin);
        hdr.nlmsg_len = msgBuf.size() - nlbegin;
        hdr.nlmsg_type = RTM_NEWLINK;
        hdr.nlmsg_flags = NLM_F_MULTI;
        msgBuf.resize(NLMSG_ALIGN(msgBuf.size()), '\0');
    }
    const auto nlbegin = msgBuf.size();
    msgBuf.append(NLMSG_SPACE(0), '\0');
    auto& hdr = *reinterpret_cast<nlmsghdr*>(msgBuf.data() + nlbegin);
    hdr.nlmsg_len = NLMSG_LENGTH(0);
    hdr.nlmsg_type = NLMSG_DONE;
    hdr.nlmsg_flags = NLM_F_MULTI;

    msgs.emplace(std::move(msgBuf));
    return in.size();
}

ssize_t sendmsg_ack(std::queue<std::string>& msgs, std::string_view in)
{
    nlmsgerr ack{};
    nlmsghdr hdr{};
    hdr.nlmsg_len = NLMSG_LENGTH(sizeof(ack));
    hdr.nlmsg_type = NLMSG_ERROR;
    auto& out = msgs.emplace(hdr.nlmsg_len, '\0');
    memcpy(out.data(), &hdr, sizeof(hdr));
    memcpy(NLMSG_DATA(out.data()), &ack, sizeof(ack));
    return in.size();
}

extern "C" {

int ioctl(int fd, unsigned long int request, ...)
{
    va_list vl;
    va_start(vl, request);
    void* data = va_arg(vl, void*);
    va_end(vl);

    auto req = reinterpret_cast<ifreq*>(data);
    if (request == SIOCGIFFLAGS)
    {
        auto it = mock_if.find(req->ifr_name);
        if (it == mock_if.end())
        {
            errno = ENXIO;
            return -1;
        }
        req->ifr_flags = it->second.flags;
        return 0;
    }
    else if (request == SIOCGIFMTU)
    {
        auto it = mock_if.find(req->ifr_name);
        if (it == mock_if.end())
        {
            errno = ENXIO;
            return -1;
        }
        if (!it->second.mtu)
        {
            errno = EOPNOTSUPP;
            return -1;
        }
        req->ifr_mtu = *it->second.mtu;
        return 0;
    }

    static auto real_ioctl =
        reinterpret_cast<decltype(&ioctl)>(dlsym(RTLD_NEXT, "ioctl"));
    return real_ioctl(fd, request, data);
}

int socket(int domain, int type, int protocol)
{
    static auto real_socket =
        reinterpret_cast<decltype(&socket)>(dlsym(RTLD_NEXT, "socket"));
    int fd = real_socket(domain, type, protocol);
    if (domain == AF_NETLINK && !(type & SOCK_RAW))
    {
        fprintf(stderr, "Netlink sockets must be RAW\n");
        abort();
    }
    if (domain == AF_NETLINK && protocol == NETLINK_ROUTE)
    {
        mock_rtnetlinks[fd] = {};
    }
    return fd;
}

int close(int fd)
{
    auto it = mock_rtnetlinks.find(fd);
    if (it != mock_rtnetlinks.end())
    {
        mock_rtnetlinks.erase(it);
    }

    static auto real_close =
        reinterpret_cast<decltype(&close)>(dlsym(RTLD_NEXT, "close"));
    return real_close(fd);
}

ssize_t sendmsg(int sockfd, const struct msghdr* msg, int flags)
{
    auto it = mock_rtnetlinks.find(sockfd);
    if (it == mock_rtnetlinks.end())
    {
        static auto real_sendmsg =
            reinterpret_cast<decltype(&sendmsg)>(dlsym(RTLD_NEXT, "sendmsg"));
        return real_sendmsg(sockfd, msg, flags);
    }
    auto& msgs = it->second;

    validateMsgHdr(msg);
    if (!msgs.empty())
    {
        fprintf(stderr, "Unread netlink responses\n");
        abort();
    }

    ssize_t ret;
    std::string_view iov(reinterpret_cast<char*>(msg->msg_iov[0].iov_base),
                         msg->msg_iov[0].iov_len);

    ret = sendmsg_link_dump(msgs, iov);
    if (ret != 0)
    {
        return ret;
    }

    ret = sendmsg_ack(msgs, iov);
    if (ret != 0)
    {
        return ret;
    }

    errno = ENOSYS;
    return -1;
}

ssize_t recvmsg(int sockfd, struct msghdr* msg, int flags)
{
    auto it = mock_rtnetlinks.find(sockfd);
    if (it == mock_rtnetlinks.end())
    {
        static auto real_recvmsg =
            reinterpret_cast<decltype(&recvmsg)>(dlsym(RTLD_NEXT, "recvmsg"));
        return real_recvmsg(sockfd, msg, flags);
    }
    auto& msgs = it->second;

    validateMsgHdr(msg);
    constexpr size_t required_buf_size = 8192;
    if (msg->msg_iov[0].iov_len < required_buf_size)
    {
        fprintf(stderr, "recvmsg iov too short: %zu\n",
                msg->msg_iov[0].iov_len);
        abort();
    }
    if (msgs.empty())
    {
        fprintf(stderr, "No pending netlink responses\n");
        abort();
    }

    ssize_t ret = 0;
    auto data = reinterpret_cast<char*>(msg->msg_iov[0].iov_base);
    while (!msgs.empty())
    {
        const auto& msg = msgs.front();
        if (NLMSG_ALIGN(ret) + msg.size() > required_buf_size)
        {
            break;
        }
        ret = NLMSG_ALIGN(ret);
        memcpy(data + ret, msg.data(), msg.size());
        ret += msg.size();
        msgs.pop();
    }
    return ret;
}

} // extern "C"
