// C++17 + libcurl. Execute somente no servidor.
#include <curl/curl.h>
#include <cstdlib>
#include <iostream>
#include <memory>
#include <regex>
#include <stdexcept>
#include <string>

struct CurlRuntime {
    CurlRuntime() {
        if (curl_global_init(CURL_GLOBAL_DEFAULT) != CURLE_OK)
            throw std::runtime_error("Falha ao iniciar libcurl.");
    }
    ~CurlRuntime() { curl_global_cleanup(); }
};
size_t append(char* data, size_t size, size_t count, void* target) {
    try { static_cast<std::string*>(target)->append(data, size * count); }
    catch (...) { return 0; }
    return size * count;
}
int main(int argc, char** argv) {
    try {
        const char* key = std::getenv("PIX_API_KEY");
        const char* id = std::getenv("PIX_SALE_ID");
        if (!key || !*key || !id || !std::regex_match(id,
                std::regex("[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{21}")))
            throw std::runtime_error("Configure PIX_API_KEY e PIX_SALE_ID.");
        if (argc != 2 || (std::string(argv[1]) != "create" && std::string(argv[1]) != "get"))
            throw std::runtime_error("Use: ./sale create|get");
        CurlRuntime runtime;
        const auto curl = std::unique_ptr<CURL, decltype(&curl_easy_cleanup)>(curl_easy_init(), curl_easy_cleanup);
        if (!curl) throw std::runtime_error("Falha ao criar cliente HTTP.");
        const bool create = std::string(argv[1]) == "create";
        const std::string url = "https://pixlojista.com.br/v1/integration/sales" +
            (create ? std::string("") : "/" + std::string(id));
        // Persista ID e corpo antes do POST; preserve ambos em toda retentativa.
        const std::string body = "{\"sale_id\":\"" + std::string(id) +
            "\",\"amount_cents\":8990,\"reference\":\"Pedido 1042\"}";
        curl_slist* list = curl_slist_append(nullptr, ("Authorization: Bearer " + std::string(key)).c_str());
        if (!list) throw std::runtime_error("Memoria insuficiente.");
        const auto headers = std::unique_ptr<curl_slist, decltype(&curl_slist_free_all)>(list, curl_slist_free_all);
        if (!curl_slist_append(list, "Content-Type: application/json"))
            throw std::runtime_error("Memoria insuficiente.");
        std::string result;
        curl_easy_setopt(curl.get(), CURLOPT_URL, url.c_str());
        curl_easy_setopt(curl.get(), CURLOPT_HTTPHEADER, list);
        curl_easy_setopt(curl.get(), CURLOPT_TIMEOUT, 15L);
        curl_easy_setopt(curl.get(), CURLOPT_FOLLOWLOCATION, 0L);
        curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION, append);
        curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, &result);
        if (create) curl_easy_setopt(curl.get(), CURLOPT_POSTFIELDS, body.c_str());
        auto error = curl_easy_perform(curl.get());
        if (error != CURLE_OK) throw std::runtime_error(curl_easy_strerror(error));
        long status = 0;
        curl_easy_getinfo(curl.get(), CURLINFO_RESPONSE_CODE, &status);
        if (status < 200 || status >= 300)
            throw std::runtime_error("HTTP " + std::to_string(status) + ": " + result);
        std::cout << result << '\n'; // JSON: sale, brcode, qr_png_base64.
    } catch (const std::exception& error) {
        std::cerr << error.what() << '\n';
        return 1;
    }
}
