#pragma once
#include <string>
#include <map>
#include <vector>
#include <functional>

namespace includecpp {
namespace inbuilds {

// HTTP Response structure
struct HttpResponse {
    int status_code;
    std::string status_text;
    std::map<std::string, std::string> headers;
    std::string body;
    bool success;
    std::string error;
};

// HTTP Request structure
struct HttpRequest {
    std::string method;
    std::string url;
    std::map<std::string, std::string> headers;
    std::string body;
    int timeout_ms = 30000;
};

class Http {
public:
    // Simplified API - removed overloads to work with parser
    static HttpResponse get(const std::string& url);
    static HttpResponse post(const std::string& url, const std::string& body);
    static HttpResponse post_json(const std::string& url, const std::string& json);
    static HttpResponse post_form(const std::string& url, const std::map<std::string, std::string>& form_data);
    static HttpResponse put(const std::string& url, const std::string& body);
    static HttpResponse patch(const std::string& url, const std::string& body);
    static HttpResponse delete_request(const std::string& url);
    static HttpResponse head(const std::string& url);
    static HttpResponse options(const std::string& url);
    static HttpResponse request(const HttpRequest& req);
    static bool download_file(const std::string& url, const std::string& filepath);
    static bool upload_file(const std::string& url, const std::string& filepath);
    static std::string url_encode(const std::string& str);
    static std::string url_decode(const std::string& str);
    static std::map<std::string, std::string> parse_query_string(const std::string& query);
    static std::string build_query_string(const std::map<std::string, std::string>& params);
};

class Url {
public:
    // URL Parsing
    static std::string get_protocol(const std::string& url);
    static std::string get_hostname(const std::string& url);
    static int get_port(const std::string& url);
    static std::string get_path(const std::string& url);
    static std::string get_query(const std::string& url);
    static std::string get_fragment(const std::string& url);

    // URL Building
    static std::string build(const std::string& protocol, const std::string& host, int port, const std::string& path);
    static std::string join(const std::string& base, const std::string& path);

    // Validation
    static bool is_valid(const std::string& url);
    static bool is_absolute(const std::string& url);
    static bool is_relative(const std::string& url);
};

class TcpClient {
public:
    TcpClient();
    ~TcpClient();

    bool connect(const std::string& host, int port);
    bool disconnect();
    bool is_connected() const;

    int send(const std::string& data);
    std::string receive(int max_bytes = 4096);
    std::string receive_line();

    bool set_timeout(int milliseconds);
    std::string get_error() const;

private:
    void* socket_fd;  // Implementation-specific socket handle
    bool connected;
    std::string last_error;
};

class UdpSocket {
public:
    UdpSocket();
    ~UdpSocket();

    bool bind(const std::string& host, int port);
    bool close();

    int send_to(const std::string& data, const std::string& dest_host, int dest_port);
    std::string receive_from(std::string& from_host, int& from_port, int max_bytes = 4096);

    bool set_timeout(int milliseconds);
    std::string get_error() const;

private:
    void* socket_fd;
    bool is_bound;
    std::string last_error;
};

// Free functions
HttpResponse http_get(const std::string& url);
HttpResponse http_post(const std::string& url, const std::string& body);
std::string fetch(const std::string& url);

} // namespace inbuilds
} // namespace includecpp
