#ifdef LINUX
#include "net_eth_linux.h"
#include "platform.h"
#include "agent_log.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/select.h>
#include <sys/time.h>
#include <netinet/tcp.h>

// ==========================================================================
// 多进程安全：无全局锁、无死锁、TCP不干扰UDP
// ==========================================================================

void eth_socket_set_init(void)
{
}

void eth_socket_set_add(int sock)
{
}

void eth_socket_set_remove(int sock)
{
}

void eth_set_mqtt_tcp_socket(PlatformSocket tcp_sock)
{
}

// ==========================================================================
// UDP 实现
// ==========================================================================
PlatformSocket net_udp_socket_create_linux(void)
{
    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0)
    {
        agent_log_error("UDP socket create failed: %s", strerror(errno));
        return -1;
    }

    int flags = fcntl(sock, F_GETFL, 0);
    fcntl(sock, F_SETFL, flags | O_NONBLOCK);
    return sock;
}

bool_xxl net_udp_bind_linux(PlatformSocket sock, uint16_xxl port)
{
    if (sock < 0) return false_xxl;

    int opt = 1;
    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = INADDR_ANY;

    if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
    {
        agent_log_error("UDP bind port %u failed: %s", port, strerror(errno));
        return false_xxl;
    }
    return true_xxl;
}

int32_xxl net_udp_sendto_linux(PlatformSocket sock, const char* ip, uint16_xxl port, const uint8_xxl* data, uint32_xxl len)
{
    if (!ip || !data || len == 0 || sock < 0) return -1;

    struct sockaddr_in dest;
    memset(&dest, 0, sizeof(dest));
    dest.sin_family = AF_INET;
    dest.sin_port = htons(port);
    inet_pton(AF_INET, ip, &dest.sin_addr);
    return sendto(sock, data, len, 0, (struct sockaddr *)&dest, sizeof(dest));
}

int32_xxl net_udp_recvfrom_linux(PlatformSocket sock, uint8_xxl* buf, uint32_xxl max_len, char* src_ip, uint16_xxl* src_port, uint32_xxl timeout_ms)
{
    if (!buf || !max_len || sock < 0) return -1;

    fd_set fds;
    FD_ZERO(&fds);
    FD_SET(sock, &fds);

    struct timeval tv;
    tv.tv_sec = timeout_ms / 1000;
    tv.tv_usec = (timeout_ms % 1000) * 1000;

    int ret = select(sock + 1, &fds, NULL, NULL, &tv);
    if (ret <= 0) return 0;

    struct sockaddr_in src;
    socklen_t src_len = sizeof(src);
    int32_xxl rlen = recvfrom(sock, buf, max_len, 0, (struct sockaddr *)&src, &src_len);
    if (rlen <= 0) return -1;

    if (src_ip) inet_ntop(AF_INET, &src.sin_addr, src_ip, 16);
    if (src_port) *src_port = ntohs(src.sin_port);
    return rlen;
}

// ==========================================================================
// TCP 实现
// ==========================================================================
PlatformSocket net_tcp_socket_create_linux(void)
{
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0)
    {
        agent_log_error("TCP socket create failed: %s", strerror(errno));
        return PLATFORM_SOCKET_INVALID;
    }

    int enable = 1;
    setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(enable));
    return sock;
}

bool_xxl net_tcp_connect_linux(PlatformSocket sock, const char* ip, uint16_xxl port)
{
    if (sock < 0 || !ip) return false_xxl;

    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);

    if (inet_pton(AF_INET, ip, &addr.sin_addr) <= 0)
    {
        agent_log_error("invalid ip: %s", ip);
        return false_xxl;
    }

    if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0)
    {
        agent_log_error("TCP connect failed: %s", strerror(errno));
        return false_xxl;
    }
    return true_xxl;
}

int32_xxl net_tcp_send_linux(PlatformSocket sock, const uint8_xxl* data, uint32_xxl len)
{
    if (sock < 0 || !data || len == 0) return -1;
    return send(sock, data, len, 0);
}

int32_xxl net_tcp_recv_linux(PlatformSocket sock, uint8_xxl* buf, uint32_xxl max_len, uint32_xxl timeout_ms)
{
    if (sock < 0 || !buf || max_len == 0) return -1;

    fd_set fds;
    FD_ZERO(&fds);
    FD_SET(sock, &fds);

    struct timeval tv;
    tv.tv_sec = timeout_ms / 1000;
    tv.tv_usec = (timeout_ms % 1000) * 1000;

    int ret = select(sock + 1, &fds, NULL, NULL, &tv);
    if (ret <= 0) return 0;
    return recv(sock, buf, max_len, 0);
}

void net_socket_close_linux(PlatformSocket sock)
{
    if (sock >= 0) close(sock);
}

NetErr net_eth_linux_init(void)
{
    agent_log_info("Linux Ethernet initialized");
    return NET_OK;
}

bool_xxl platform_check_port_in_use_linux(uint16_xxl port)
{
    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0) return true_xxl;

    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = INADDR_ANY;

    int ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
    close(sock);
    return ret < 0 ? true_xxl : false_xxl;
}

#endif
