// ============================================================
// vqt6/_bridge_network.cpp — QtNetwork C 桥接层实现
// ============================================================

#include "_bridge.h"
#include "_bridge_network.h"
#include <QHostAddress>
#include <QAbstractSocket>
#include <QTcpSocket>
#include <QUdpSocket>
#include <QNetworkRequest>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QHttpHeaders>
#include <QHttp2Configuration>
#include <QNetworkCookieJar>

// ============================================================
// QHostAddress
// ============================================================
extern "C" VQT6_API void* vqt6_qhostaddress_create(void) {
    return new QHostAddress();
}

extern "C" VQT6_API void* vqt6_qhostaddress_create_with_ipv4(uint32_t ipv4) {
    return new QHostAddress(static_cast<quint32>(ipv4));
}

extern "C" VQT6_API void* vqt6_qhostaddress_create_with_string(void* address) {
    if (address == nullptr) return new QHostAddress();
    return new QHostAddress(*static_cast<QString*>(address));
}

extern "C" VQT6_API void* vqt6_qhostaddress_create_with_local_host(void) {
    return new QHostAddress(QHostAddress::LocalHost);
}

extern "C" VQT6_API void* vqt6_qhostaddress_create_with_local_ipv4(void) {
    return new QHostAddress(QHostAddress::LocalHostIPv4);
}

extern "C" VQT6_API void* vqt6_qhostaddress_create_with_broadcast(void) {
    return new QHostAddress(QHostAddress::Broadcast);
}

extern "C" VQT6_API void* vqt6_qhostaddress_create_with_any_ipv4(void) {
    return new QHostAddress(QHostAddress::AnyIPv4);
}

extern "C" VQT6_API void* vqt6_qhostaddress_to_string(void* addr) {
    if (addr == nullptr) return nullptr;
    return new QString(static_cast<QHostAddress*>(addr)->toString());
}

extern "C" VQT6_API uint32_t vqt6_qhostaddress_to_ipv4(void* addr) {
    if (addr == nullptr) return 0;
    return static_cast<uint32_t>(static_cast<QHostAddress*>(addr)->toIPv4Address());
}

extern "C" VQT6_API int vqt6_qhostaddress_is_null(void* addr) {
    if (addr == nullptr) return 0;
    return static_cast<QHostAddress*>(addr)->isNull() ? 1 : 0;
}

extern "C" VQT6_API int vqt6_qhostaddress_is_loopback(void* addr) {
    if (addr == nullptr) return 0;
    return static_cast<QHostAddress*>(addr)->isLoopback() ? 1 : 0;
}

extern "C" VQT6_API int vqt6_qhostaddress_is_broadcast(void* addr) {
    if (addr == nullptr) return 0;
    return static_cast<QHostAddress*>(addr)->isBroadcast() ? 1 : 0;
}

extern "C" VQT6_API int vqt6_qhostaddress_protocol(void* addr) {
    if (addr == nullptr) return 0;
    return static_cast<int>(static_cast<QHostAddress*>(addr)->protocol());
}

extern "C" VQT6_API void vqt6_qhostaddress_free(void* addr) {
    delete static_cast<QHostAddress*>(addr);
}

// ============================================================
// QAbstractSocket
// ============================================================
extern "C" VQT6_API int vqt6_qabstractsocket_state(void* socket) {
    if (socket == nullptr) return 0;
    return static_cast<int>(static_cast<QAbstractSocket*>(socket)->state());
}

extern "C" VQT6_API int vqt6_qabstractsocket_error(void* socket) {
    if (socket == nullptr) return 0;
    return static_cast<int>(static_cast<QAbstractSocket*>(socket)->error());
}

extern "C" VQT6_API void* vqt6_qabstractsocket_error_string(void* socket) {
    if (socket == nullptr) return nullptr;
    return new QString(static_cast<QAbstractSocket*>(socket)->errorString());
}

extern "C" VQT6_API void vqt6_qabstractsocket_connect_to_host(void* socket, void* host_name, uint16_t port) {
    if (socket == nullptr || host_name == nullptr) return;
    static_cast<QAbstractSocket*>(socket)->connectToHost(*static_cast<QString*>(host_name), port);
}

extern "C" VQT6_API void vqt6_qabstractsocket_connect_to_host_with_addr(void* socket, void* address, uint16_t port) {
    if (socket == nullptr || address == nullptr) return;
    static_cast<QAbstractSocket*>(socket)->connectToHost(*static_cast<QHostAddress*>(address), port);
}

extern "C" VQT6_API void vqt6_qabstractsocket_disconnect_from_host(void* socket) {
    if (socket == nullptr) return;
    static_cast<QAbstractSocket*>(socket)->disconnectFromHost();
}

extern "C" VQT6_API int vqt6_qabstractsocket_wait_for_connected(void* socket, int timeout_ms) {
    if (socket == nullptr) return 0;
    return static_cast<QAbstractSocket*>(socket)->waitForConnected(timeout_ms) ? 1 : 0;
}

extern "C" VQT6_API int vqt6_qabstractsocket_wait_for_ready_read(void* socket, int timeout_ms) {
    if (socket == nullptr) return 0;
    return static_cast<QAbstractSocket*>(socket)->waitForReadyRead(timeout_ms) ? 1 : 0;
}

extern "C" VQT6_API int vqt6_qabstractsocket_wait_for_bytes_written(void* socket, int timeout_ms) {
    if (socket == nullptr) return 0;
    return static_cast<QAbstractSocket*>(socket)->waitForBytesWritten(timeout_ms) ? 1 : 0;
}

extern "C" VQT6_API int vqt6_qabstractsocket_wait_for_disconnected(void* socket, int timeout_ms) {
    if (socket == nullptr) return 0;
    return static_cast<QAbstractSocket*>(socket)->waitForDisconnected(timeout_ms) ? 1 : 0;
}

extern "C" VQT6_API int vqt6_qabstractsocket_is_valid(void* socket) {
    if (socket == nullptr) return 0;
    return static_cast<QAbstractSocket*>(socket)->isValid() ? 1 : 0;
}

extern "C" VQT6_API int vqt6_qabstractsocket_is_open(void* socket) {
    if (socket == nullptr) return 0;
    return static_cast<QAbstractSocket*>(socket)->isOpen() ? 1 : 0;
}

extern "C" VQT6_API int vqt6_qabstractsocket_flush(void* socket) {
    if (socket == nullptr) return 0;
    return static_cast<QAbstractSocket*>(socket)->flush() ? 1 : 0;
}

extern "C" VQT6_API void vqt6_qabstractsocket_close(void* socket) {
    if (socket == nullptr) return;
    static_cast<QAbstractSocket*>(socket)->close();
}

extern "C" VQT6_API void vqt6_qabstractsocket_abort(void* socket) {
    if (socket == nullptr) return;
    static_cast<QAbstractSocket*>(socket)->abort();
}

extern "C" VQT6_API size_t vqt6_qabstractsocket_read(void* socket, void* buf, size_t max_size) {
    if (socket == nullptr || buf == nullptr) return 0;
    return static_cast<size_t>(static_cast<QAbstractSocket*>(socket)->read(static_cast<char*>(buf), static_cast<qint64>(max_size)));
}

extern "C" VQT6_API void* vqt6_qabstractsocket_read_all(void* socket, size_t* out_size) {
    if (socket == nullptr) return nullptr;
    QByteArray ba = static_cast<QAbstractSocket*>(socket)->readAll();
    if (out_size != nullptr) *out_size = static_cast<size_t>(ba.size());
    return ba.data();
}

extern "C" VQT6_API size_t vqt6_qabstractsocket_write(void* socket, const void* data, size_t size) {
    if (socket == nullptr || data == nullptr) return 0;
    return static_cast<size_t>(static_cast<QAbstractSocket*>(socket)->write(static_cast<const char*>(data), static_cast<qint64>(size)));
}

extern "C" VQT6_API size_t vqt6_qabstractsocket_bytes_available(void* socket) {
    if (socket == nullptr) return 0;
    return static_cast<size_t>(static_cast<QAbstractSocket*>(socket)->bytesAvailable());
}

extern "C" VQT6_API size_t vqt6_qabstractsocket_bytes_to_write(void* socket) {
    if (socket == nullptr) return 0;
    return static_cast<size_t>(static_cast<QAbstractSocket*>(socket)->bytesToWrite());
}

extern "C" VQT6_API void* vqt6_qabstractsocket_peer_address(void* socket) {
    if (socket == nullptr) return nullptr;
    return new QHostAddress(static_cast<QAbstractSocket*>(socket)->peerAddress());
}

extern "C" VQT6_API uint16_t vqt6_qabstractsocket_peer_port(void* socket) {
    if (socket == nullptr) return 0;
    return static_cast<uint16_t>(static_cast<QAbstractSocket*>(socket)->peerPort());
}

extern "C" VQT6_API void* vqt6_qabstractsocket_local_address(void* socket) {
    if (socket == nullptr) return nullptr;
    return new QHostAddress(static_cast<QAbstractSocket*>(socket)->localAddress());
}

extern "C" VQT6_API uint16_t vqt6_qabstractsocket_local_port(void* socket) {
    if (socket == nullptr) return 0;
    return static_cast<uint16_t>(static_cast<QAbstractSocket*>(socket)->localPort());
}

// ============================================================
// QTcpSocket
// ============================================================
extern "C" VQT6_API void* vqt6_qtcpsocket_create(void) {
    return new QTcpSocket();
}

extern "C" VQT6_API void* vqt6_qtcpsocket_create_with_parent(void* parent) {
    if (parent == nullptr) return nullptr;
    return new QTcpSocket(static_cast<QObject*>(parent));
}

extern "C" VQT6_API void vqt6_qtcpsocket_connect_to_host(void* socket, void* host_name, uint16_t port, int mode) {
    if (socket == nullptr || host_name == nullptr) return;
    static_cast<QTcpSocket*>(socket)->connectToHost(*static_cast<QString*>(host_name), port,
                                                    static_cast<QIODevice::OpenMode>(mode));
}

extern "C" VQT6_API void vqt6_qtcpsocket_connect_to_host_with_addr(void* socket, void* address, uint16_t port, int mode) {
    if (socket == nullptr || address == nullptr) return;
    static_cast<QTcpSocket*>(socket)->connectToHost(*static_cast<QHostAddress*>(address), port,
                                                    static_cast<QIODevice::OpenMode>(mode));
}

extern "C" VQT6_API int vqt6_qtcpsocket_set_socket_descriptor(void* socket, intptr_t socket_descriptor) {
    if (socket == nullptr) return 0;
    return static_cast<QTcpSocket*>(socket)->setSocketDescriptor(static_cast<qintptr>(socket_descriptor)) ? 1 : 0;
}

extern "C" VQT6_API intptr_t vqt6_qtcpsocket_socket_descriptor(void* socket) {
    if (socket == nullptr) return -1;
    return static_cast<intptr_t>(static_cast<QTcpSocket*>(socket)->socketDescriptor());
}

extern "C" VQT6_API void vqt6_qtcpsocket_set_proxy(void* socket, int proxy_type) {
    Q_UNUSED(socket);
    Q_UNUSED(proxy_type);
    // QNetworkProxy 配置在更高层
}

extern "C" VQT6_API void vqt6_qtcpsocket_abort(void* socket) {
    if (socket == nullptr) return;
    static_cast<QTcpSocket*>(socket)->abort();
}

// ============================================================
// QUdpSocket
// ============================================================
extern "C" VQT6_API void* vqt6_qudpsocket_create(void) {
    return new QUdpSocket();
}

extern "C" VQT6_API void* vqt6_qudpsocket_create_with_parent(void* parent) {
    if (parent == nullptr) return nullptr;
    return new QUdpSocket(static_cast<QObject*>(parent));
}

extern "C" VQT6_API int vqt6_qudpsocket_bind(void* socket, uint16_t port) {
    if (socket == nullptr) return 0;
    return static_cast<QUdpSocket*>(socket)->bind(port) ? 1 : 0;
}

extern "C" VQT6_API int vqt6_qudpsocket_bind_with_addr(void* socket, void* address, uint16_t port) {
    if (socket == nullptr || address == nullptr) return 0;
    return static_cast<QUdpSocket*>(socket)->bind(*static_cast<QHostAddress*>(address), port) ? 1 : 0;
}

extern "C" VQT6_API void vqt6_qudpsocket_close(void* socket) {
    if (socket == nullptr) return;
    static_cast<QUdpSocket*>(socket)->close();
}

extern "C" VQT6_API size_t vqt6_qudpsocket_write_datagram(void* socket, const void* data, size_t size, void* host, uint16_t port) {
    if (socket == nullptr || data == nullptr || host == nullptr) return 0;
    return static_cast<size_t>(static_cast<QUdpSocket*>(socket)->writeDatagram(
        static_cast<const char*>(data), static_cast<qint64>(size),
        *static_cast<QHostAddress*>(host), port));
}

extern "C" VQT6_API size_t vqt6_qudpsocket_read_datagram(void* socket, void* data, size_t max_size, void* host, uint16_t* port) {
    if (socket == nullptr || data == nullptr) return 0;
    QHostAddress sender;
    quint16 sender_port = 0;
    qint64 n = static_cast<QUdpSocket*>(socket)->readDatagram(
        static_cast<char*>(data), static_cast<qint64>(max_size), &sender, &sender_port);
    if (host != nullptr) {
        QHostAddress* dst = static_cast<QHostAddress*>(host);
        *dst = sender;
    }
    if (port != nullptr) {
        *port = sender_port;
    }
    return static_cast<size_t>(n);
}

extern "C" VQT6_API int vqt6_qudpsocket_has_pending_datagrams(void* socket) {
    if (socket == nullptr) return 0;
    return static_cast<QUdpSocket*>(socket)->hasPendingDatagrams() ? 1 : 0;
}

extern "C" VQT6_API size_t vqt6_qudpsocket_pending_datagram_size(void* socket) {
    if (socket == nullptr) return 0;
    return static_cast<size_t>(static_cast<QUdpSocket*>(socket)->pendingDatagramSize());
}

extern "C" VQT6_API int vqt6_qudpsocket_join_multicast_group(void* socket, void* group_address) {
    if (socket == nullptr || group_address == nullptr) return 0;
    return static_cast<QUdpSocket*>(socket)->joinMulticastGroup(*static_cast<QHostAddress*>(group_address)) ? 1 : 0;
}

extern "C" VQT6_API int vqt6_qudpsocket_leave_multicast_group(void* socket, void* group_address) {
    if (socket == nullptr || group_address == nullptr) return 0;
    return static_cast<QUdpSocket*>(socket)->leaveMulticastGroup(*static_cast<QHostAddress*>(group_address)) ? 1 : 0;
}

// ============================================================
// QNetworkRequest
// ============================================================
extern "C" VQT6_API void* vqt6_qnetworkrequest_create(void) {
    return new QNetworkRequest();
}

extern "C" VQT6_API void* vqt6_qnetworkrequest_create_with_url(void* url) {
    if (url == nullptr) return new QNetworkRequest();
    return new QNetworkRequest(QUrl(*static_cast<QString*>(url)));
}

extern "C" VQT6_API void vqt6_qnetworkrequest_set_url(void* req, void* url) {
    if (req == nullptr || url == nullptr) return;
    static_cast<QNetworkRequest*>(req)->setUrl(QUrl(*static_cast<QString*>(url)));
}

extern "C" VQT6_API void* vqt6_qnetworkrequest_url(void* req) {
    if (req == nullptr) return nullptr;
    return new QString(static_cast<QNetworkRequest*>(req)->url().toString());
}

extern "C" VQT6_API void vqt6_qnetworkrequest_set_header(void* req, int header_type, void* value) {
    if (req == nullptr || value == nullptr) return;
    static_cast<QNetworkRequest*>(req)->setHeader(static_cast<QNetworkRequest::KnownHeaders>(header_type),
                                                  *static_cast<QVariant*>(value));
}

extern "C" VQT6_API void* vqt6_qnetworkrequest_header(void* req, int header_type) {
    if (req == nullptr) return nullptr;
    return new QVariant(static_cast<QNetworkRequest*>(req)->header(static_cast<QNetworkRequest::KnownHeaders>(header_type)));
}

extern "C" VQT6_API void vqt6_qnetworkrequest_set_raw_header(void* req, const char* header_name, const void* value, size_t value_size) {
    if (req == nullptr || header_name == nullptr) return;
    static_cast<QNetworkRequest*>(req)->setRawHeader(QByteArray(header_name),
                                                      QByteArray(static_cast<const char*>(value), static_cast<int>(value_size)));
}

extern "C" VQT6_API void* vqt6_qnetworkrequest_raw_header(void* req, const char* header_name, size_t* out_size) {
    if (req == nullptr || header_name == nullptr) return nullptr;
    QByteArray ba = static_cast<QNetworkRequest*>(req)->rawHeader(QByteArray(header_name));
    if (out_size != nullptr) *out_size = static_cast<size_t>(ba.size());
    return ba.data();
}

extern "C" VQT6_API void vqt6_qnetworkrequest_set_attribute(void* req, int attr_type, void* value) {
    if (req == nullptr || value == nullptr) return;
    static_cast<QNetworkRequest*>(req)->setAttribute(static_cast<QNetworkRequest::Attribute>(attr_type),
                                                      *static_cast<QVariant*>(value));
}

extern "C" VQT6_API void* vqt6_qnetworkrequest_attribute(void* req, int attr_type) {
    if (req == nullptr) return nullptr;
    return new QVariant(static_cast<QNetworkRequest*>(req)->attribute(static_cast<QNetworkRequest::Attribute>(attr_type)));
}

extern "C" VQT6_API void vqt6_qnetworkrequest_free(void* req) {
    delete static_cast<QNetworkRequest*>(req);
}

// ============================================================
// QNetworkAccessManager
// ============================================================
extern "C" VQT6_API void* vqt6_qnetworkaccessmanager_create(void) {
    return new QNetworkAccessManager();
}

extern "C" VQT6_API void* vqt6_qnetworkaccessmanager_create_with_parent(void* parent) {
    if (parent == nullptr) return nullptr;
    return new QNetworkAccessManager(static_cast<QObject*>(parent));
}

extern "C" VQT6_API void* vqt6_qnetworkaccessmanager_get(void* nam, void* req) {
    if (nam == nullptr || req == nullptr) return nullptr;
    return static_cast<QNetworkAccessManager*>(nam)->get(*static_cast<QNetworkRequest*>(req));
}

extern "C" VQT6_API void* vqt6_qnetworkaccessmanager_post(void* nam, void* req, const void* data, size_t size) {
    if (nam == nullptr || req == nullptr) return nullptr;
    QByteArray payload;
    if (data != nullptr && size > 0) {
        payload = QByteArray(static_cast<const char*>(data), static_cast<int>(size));
    }
    return static_cast<QNetworkAccessManager*>(nam)->post(*static_cast<QNetworkRequest*>(req), payload);
}

extern "C" VQT6_API void* vqt6_qnetworkaccessmanager_put(void* nam, void* req, const void* data, size_t size) {
    if (nam == nullptr || req == nullptr) return nullptr;
    QByteArray payload;
    if (data != nullptr && size > 0) {
        payload = QByteArray(static_cast<const char*>(data), static_cast<int>(size));
    }
    return static_cast<QNetworkAccessManager*>(nam)->put(*static_cast<QNetworkRequest*>(req), payload);
}

extern "C" VQT6_API void* vqt6_qnetworkaccessmanager_delete_resource(void* nam, void* req) {
    if (nam == nullptr || req == nullptr) return nullptr;
    return static_cast<QNetworkAccessManager*>(nam)->deleteResource(*static_cast<QNetworkRequest*>(req));
}

extern "C" VQT6_API void* vqt6_qnetworkaccessmanager_head(void* nam, void* req) {
    if (nam == nullptr || req == nullptr) return nullptr;
    return static_cast<QNetworkAccessManager*>(nam)->head(*static_cast<QNetworkRequest*>(req));
}

extern "C" VQT6_API void vqt6_qnetworkaccessmanager_set_cookie_store(void* nam, void* store) {
    if (nam == nullptr || store == nullptr) return;
    QNetworkCookieJar* jar = qobject_cast<QNetworkCookieJar*>(static_cast<QObject*>(store));
    if (jar != nullptr) {
        static_cast<QNetworkAccessManager*>(nam)->setCookieJar(jar);
    }
}

// ============================================================
// QNetworkReply
// ============================================================
extern "C" VQT6_API void* vqt6_qnetworkreply_url(void* reply) {
    if (reply == nullptr) return nullptr;
    return new QString(static_cast<QNetworkReply*>(reply)->url().toString());
}

extern "C" VQT6_API void* vqt6_qnetworkreply_request(void* reply) {
    if (reply == nullptr) return nullptr;
    return new QNetworkRequest(static_cast<QNetworkReply*>(reply)->request());
}

extern "C" VQT6_API int vqt6_qnetworkreply_error(void* reply) {
    if (reply == nullptr) return 0;
    return static_cast<int>(static_cast<QNetworkReply*>(reply)->error());
}

extern "C" VQT6_API void* vqt6_qnetworkreply_error_string(void* reply) {
    if (reply == nullptr) return nullptr;
    return new QString(static_cast<QNetworkReply*>(reply)->errorString());
}

extern "C" VQT6_API int vqt6_qnetworkreply_is_finished(void* reply) {
    if (reply == nullptr) return 0;
    return static_cast<QNetworkReply*>(reply)->isFinished() ? 1 : 0;
}

extern "C" VQT6_API int vqt6_qnetworkreply_is_running(void* reply) {
    if (reply == nullptr) return 0;
    return static_cast<QNetworkReply*>(reply)->isRunning() ? 1 : 0;
}

extern "C" VQT6_API void vqt6_qnetworkreply_abort(void* reply) {
    if (reply == nullptr) return;
    static_cast<QNetworkReply*>(reply)->abort();
}

extern "C" VQT6_API size_t vqt6_qnetworkreply_read(void* reply, void* buf, size_t max_size) {
    if (reply == nullptr || buf == nullptr) return 0;
    return static_cast<size_t>(static_cast<QNetworkReply*>(reply)->read(static_cast<char*>(buf), static_cast<qint64>(max_size)));
}

extern "C" VQT6_API void* vqt6_qnetworkreply_read_all(void* reply, size_t* out_size) {
    if (reply == nullptr) return nullptr;
    QByteArray ba = static_cast<QNetworkReply*>(reply)->readAll();
    if (out_size != nullptr) *out_size = static_cast<size_t>(ba.size());
    return ba.data();
}

extern "C" VQT6_API size_t vqt6_qnetworkreply_bytes_available(void* reply) {
    if (reply == nullptr) return 0;
    return static_cast<size_t>(static_cast<QNetworkReply*>(reply)->bytesAvailable());
}

extern "C" VQT6_API void* vqt6_qnetworkreply_header(void* reply, int header_type) {
    if (reply == nullptr) return nullptr;
    return new QVariant(static_cast<QNetworkReply*>(reply)->header(static_cast<QNetworkRequest::KnownHeaders>(header_type)));
}

extern "C" VQT6_API void* vqt6_qnetworkreply_raw_header(void* reply, const char* header_name, size_t* out_size) {
    if (reply == nullptr || header_name == nullptr) return nullptr;
    QByteArray ba = static_cast<QNetworkReply*>(reply)->rawHeader(QByteArray(header_name));
    if (out_size != nullptr) *out_size = static_cast<size_t>(ba.size());
    return ba.data();
}

extern "C" VQT6_API void* vqt6_qnetworkreply_attribute(void* reply, int attribute_code) {
    if (reply == nullptr) return nullptr;
    return new QVariant(static_cast<QNetworkReply*>(reply)->attribute(static_cast<QNetworkRequest::Attribute>(attribute_code)));
}

extern "C" VQT6_API int vqt6_qnetworkreply_attribute_int(void* reply, int attribute_code, int default_value) {
    if (reply == nullptr) return default_value;
    return static_cast<QNetworkReply*>(reply)->attribute(static_cast<QNetworkRequest::Attribute>(attribute_code)).toInt(default_value);
}

extern "C" VQT6_API void vqt6_qnetworkreply_set_raw_header(void* reply, const char* header_name, const void* value, size_t value_size) {
    if (reply == nullptr || header_name == nullptr) return;
    static_cast<QNetworkReply*>(reply)->setRawHeader(QByteArray(header_name),
                                                      QByteArray(static_cast<const char*>(value), static_cast<int>(value_size)));
}
