// C++ Integration Example
#include <iostream>
#include <string>
#include <fstream>
#include <curl/curl.h>
#include <json/json.h>
#include <base64.h>

class MayaPdfFiller {
private:
    std::string apiKey;
    std::string baseUrl = "https://api.mayapdffiller.com";
    
    struct APIResponse {
        std::string data;
        long responseCode;
    };
    
    static size_t WriteCallback(void* contents, size_t size, size_t nmemb, APIResponse* response) {
        size_t totalSize = size * nmemb;
        response->data.append(static_cast<char*>(contents), totalSize);
        return totalSize;
    }
    
    APIResponse makeRequest(const std::string& endpoint, const std::string& jsonData) {
        CURL* curl;
        APIResponse response;
        
        curl = curl_easy_init();
        if (curl) {
            std::string url = baseUrl + endpoint;
            std::string authHeader = "Authorization: Bearer " + apiKey;
            
            struct curl_slist* headers = nullptr;
            headers = curl_slist_append(headers, "Content-Type: application/json");
            headers = curl_slist_append(headers, authHeader.c_str());
            
            curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
            curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonData.c_str());
            curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
            
            CURLcode res = curl_easy_perform(curl);
            curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response.responseCode);
            
            curl_slist_free_all(headers);
            curl_easy_cleanup(curl);
        }
        
        return response;
    }
    
public:
    MayaPdfFiller(const std::string& key) : apiKey(key) {}
    
    Json::Value fillPdf(const std::string& templatePath, const Json::Value& data) {
        // Read PDF file
        std::ifstream file(templatePath, std::ios::binary);
        if (!file.is_open()) {
            throw std::runtime_error("Cannot open template file: " + templatePath);
        }
        
        std::string pdfContent((std::istreambuf_iterator<char>(file)),
                              std::istreambuf_iterator<char>());
        file.close();
        
        // Encode to base64
        std::string encodedPdf = base64_encode(pdfContent);
        
        // Prepare JSON payload
        Json::Value payload;
        payload["template_pdf"] = encodedPdf;
        payload["data"] = data;
        
        Json::StreamWriterBuilder builder;
        std::string jsonString = Json::writeString(builder, payload);
        
        // Make API request
        APIResponse response = makeRequest("/pdf/fill", jsonString);
        
        if (response.responseCode != 200) {
            throw std::runtime_error("API request failed with code: " + std::to_string(response.responseCode));
        }
        
        // Parse response
        Json::Value jsonResponse;
        Json::CharReaderBuilder readerBuilder;
        std::string errs;
        std::istringstream s(response.data);
        
        if (!Json::parseFromStream(readerBuilder, s, &jsonResponse, &errs)) {
            throw std::runtime_error("Failed to parse JSON response: " + errs);
        }
        
        return jsonResponse;
    }
    
    Json::Value analyzeTemplate(const std::string& templatePath) {
        std::ifstream file(templatePath, std::ios::binary);
        if (!file.is_open()) {
            throw std::runtime_error("Cannot open template file: " + templatePath);
        }
        
        std::string pdfContent((std::istreambuf_iterator<char>(file)),
                              std::istreambuf_iterator<char>());
        file.close();
        
        Json::Value payload;
        payload["template_pdf"] = base64_encode(pdfContent);
        
        Json::StreamWriterBuilder builder;
        std::string jsonString = Json::writeString(builder, payload);
        
        APIResponse response = makeRequest("/pdf/analyze", jsonString);
        
        Json::Value jsonResponse;
        Json::CharReaderBuilder readerBuilder;
        std::string errs;
        std::istringstream s(response.data);
        Json::parseFromStream(readerBuilder, s, &jsonResponse, &errs);
        
        return jsonResponse;
    }
    
    void savePdfToFile(const Json::Value& result, const std::string& outputPath) {
        if (!result["success"].asBool()) {
            throw std::runtime_error("PDF filling was not successful");
        }
        
        std::string encodedPdf = result["filled_pdf"].asString();
        std::string pdfContent = base64_decode(encodedPdf);
        
        std::ofstream outFile(outputPath, std::ios::binary);
        if (!outFile.is_open()) {
            throw std::runtime_error("Cannot create output file: " + outputPath);
        }
        
        outFile.write(pdfContent.c_str(), pdfContent.length());
        outFile.close();
    }
};

// Usage Example
int main() {
    try {
        MayaPdfFiller filler("your-api-key");
        
        // Analyze template first
        Json::Value analysis = filler.analyzeTemplate("templates/invoice.pdf");
        
        std::cout << "Found " << analysis["form_fields"].size() << " fields:" << std::endl;
        for (const auto& field : analysis["form_fields"]) {
            std::cout << "- " << field["name"].asString() 
                      << " (" << field["type"].asString() << ")" << std::endl;
        }
        
        // Fill PDF with data
        Json::Value data;
        data["customer_name"] = "Maya Inc";
        data["invoice_date"] = "01/15/2024";
        data["total_amount"] = "$1,250.00";
        
        Json::Value result = filler.fillPdf("templates/invoice.pdf", data);
        
        if (result["success"].asBool()) {
            filler.savePdfToFile(result, "output/filled-invoice.pdf");
            std::cout << "PDF filled successfully!" << std::endl;
            std::cout << "Processing time: " << result["processing_time"].asString() << std::endl;
        }
        
    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return 1;
    }
    
    return 0;
}

// CMakeLists.txt
/*
cmake_minimum_required(VERSION 3.10)
project(MayaPdfFillerExample)

set(CMAKE_CXX_STANDARD 17)

# Find required packages
find_package(PkgConfig REQUIRED)
pkg_check_modules(JSONCPP jsoncpp)

find_package(CURL REQUIRED)

# Include directories
include_directories(${JSONCPP_INCLUDE_DIRS})

# Add executable
add_executable(maya_pdf_example main.cpp)

# Link libraries
target_link_libraries(maya_pdf_example 
    ${CURL_LIBRARIES}
    ${JSONCPP_LIBRARIES}
)

# Compiler flags
target_compile_options(maya_pdf_example PRIVATE ${JSONCPP_CFLAGS_OTHER})
*/

// Makefile alternative
/*
CXX = g++
CXXFLAGS = -std=c++17 -Wall
LIBS = -lcurl -ljsoncpp

maya_pdf_example: main.cpp
	$(CXX) $(CXXFLAGS) -o maya_pdf_example main.cpp $(LIBS)

clean:
	rm -f maya_pdf_example

.PHONY: clean
*/