#include <iostream>
#include <string>
#include <winsock2.h>
#include <ws2tcpip.h>

#pragma comment(lib, "ws2_32.lib")

namespace Utils {

    DWORD GetIPAddr(std::string& ip_addr) {
        // 1. Initialize Winsock
        WSADATA wsaData;
        if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
            return 0;
        }

        // 2. Resolve the server address
        struct addrinfo* result = NULL, hints;
        const char* hostname = "api.ipify.org";
        const char* path = "/";

        ZeroMemory(&hints, sizeof(hints));
        hints.ai_family = AF_UNSPEC;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_protocol = IPPROTO_TCP;

        if (getaddrinfo(hostname, "80", &hints, &result) != 0) {
            WSACleanup();
            return 0;
        }

        // 3. Connect to the server
        SOCKET ConnectSocket = INVALID_SOCKET;
        struct addrinfo* ptr = NULL;

        for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {
            ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
            if (ConnectSocket == INVALID_SOCKET) {
                WSACleanup();
                return 0;
            }

            if (connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen) == SOCKET_ERROR) {
                closesocket(ConnectSocket);
                ConnectSocket = INVALID_SOCKET;
                continue;
            }
            break;
        }

        freeaddrinfo(result);

        if (ConnectSocket == INVALID_SOCKET) {
            WSACleanup();
            return 0;
        }

        // 4. Send HTTP GET request
        std::string request = "GET " + std::string(path) + " HTTP/1.1\r\n"
            "Host: " + std::string(hostname) + "\r\n"
            "User-Agent: CppWinsockClient/1.0\r\n"
            "Connection: close\r\n\r\n";

        if (send(ConnectSocket, request.c_str(), (int)request.length(), 0) == SOCKET_ERROR) {
            closesocket(ConnectSocket);
            WSACleanup();
            return 0;
        }

        // 5. Receive the response
        char recvbuf[4096];
        int iResult;
        std::string responseData;

        do {
            iResult = recv(ConnectSocket, recvbuf, sizeof(recvbuf) - 1, 0);
            if (iResult > 0) {
                recvbuf[iResult] = '\0';
                responseData += recvbuf;
            }
        } while (iResult > 0);

        // 6. Extract and print ONLY the IP (Body)
        // The body is separated from headers by a double newline "\r\n\r\n"
        size_t headerEnd = responseData.find("\r\n\r\n");
        if (headerEnd != std::string::npos) {
            std::string ip = responseData.substr(headerEnd + 4);
            ip_addr = ip;
            //std::cout << ip << std::endl;
        }
        else {
            //std::cerr << "Invalid response format" << std::endl;
            closesocket(ConnectSocket);
            WSACleanup();
            return 0;
        }

        // 7. Cleanup
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }


}