#include "net.h"
#include <curl/curl.h>
#include "../utils/utils.h"
#include <iostream>
#include <vector>
#include <regex>
#include <boost/regex.hpp>

struct data {};

size_t write_data(void *buffer, size_t size, size_t nmemb, void *filename) {
    FILE *f = fopen(((std::string *)filename)->c_str(), "w");
    size_t written = fwrite(buffer, size, nmemb, f);

    fclose(f);

    return written;
}

Net::Net() {}

void write_modules(void *buffer, size_t size, size_t nmemb, void *modules) {
    std::vector<std::string> *modules_vector =
        (std::vector<std::string> *)modules;
    std::string to_parse = std::string((char*)buffer);

    boost::regex r("(?!\\\")\\w+\\.json(?!\\\")", boost::regex::collate);
    boost::smatch res;

    std::string::const_iterator search(to_parse.cbegin());
    while (boost::regex_search(search, to_parse.cend(), res, r)) {
        modules_vector->push_back(res[0]);
        search = res.suffix().first;
    }
}

size_t writeCallback(void* contents, size_t size, size_t nmemb, void* userp) {
    size_t totalSize = size * nmemb;
    ((std::string*)userp)->append(std::string((char*)contents));
    return totalSize;
}

std::vector<std::string> Net::get_all_modules(std::string url) {
    CURL *handle = curl_easy_init();

    curl_easy_setopt(handle, CURLOPT_URL, url.c_str());
    curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_modules);

    std::vector<std::string> modules {};

    curl_easy_setopt(handle, CURLOPT_WRITEDATA, &modules);

    curl_easy_perform(handle);

    return modules;
}

void Net::get_file(std::string url, std::string filename) {
    CURL *handle = curl_easy_init();

    curl_easy_setopt(handle, CURLOPT_URL, url.c_str());

    curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_data);
    curl_easy_setopt(handle, CURLOPT_WRITEDATA, &filename);

    auto success = curl_easy_perform(handle);

    curl_easy_cleanup(handle);
}

std::string Net::fetch_check_data_from_ofdru(std::string fn, std::string fd, std::string fi, std::string datetime, int operation, int total, std::string captcha) {
    CURL *handle = curl_easy_init();
    if (handle == nullptr) {
        std::cerr << "cannot initialize curl" << std::endl;
        return "";
    }
    struct curl_slist *headers = NULL;
    std::string readBuffer = "";

    curl_easy_setopt(handle, CURLOPT_URL, "https://check.ofd.ru/Document/FetchReceiptFromFns");

    headers = curl_slist_append(headers, "Content-Type: application/json;charset=UTF-8");
    curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers);

    std::string dataJSON =
        "{"
        "\"TotalSum\":" + std::to_string(total) + ","
        "\"FnNumber\":\"" + fn + "\","
        "\"ReceiptOperationType\":\"" + std::to_string(operation) + "\","
        "\"DocNumber\":\"" + fd + "\","
        "\"DocFiscalSign\":\"" + fi + "\","
        "\"Captcha\":\"" + captcha + "\","
        "\"DocDateTime\":\"" + datetime + ".000Z\""
        "}";

    curl_easy_setopt(handle, CURLOPT_POSTFIELDS, dataJSON.c_str());
    curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, writeCallback);
    curl_easy_setopt(handle, CURLOPT_WRITEDATA, &readBuffer);

    auto answer = curl_easy_perform(handle);

    delete headers;
    curl_easy_cleanup(handle);

    return readBuffer;
}

void Net::get_captcha_from_ofdru() {
    get_file("https://check.ofd.ru/api/captcha/common/img", get_path_relative_to_home(".local/share/checks_parser/captcha.jpg"));
}