#include <maps/libs/log8/include/log8.h>
#include <maps/libs/cmdline/include/cmdline.h>
#include <maps/libs/common/include/exception.h>

#include <maps/libs/json/include/value.h>
#include <maps/libs/json/include/builder.h>

#include <maps/wikimap/mapspro/services/autocart/pipeline/libs/storage/include/publication_results.h>

#include <fstream>

using namespace maps::wiki::autocart::pipeline;

namespace json = maps::json;

int main(int argc, const char** argv)
try {
    NYT::Initialize(argc, argv);

    maps::cmdline::Parser parser("Filter accepted buildings");

    maps::cmdline::Option<std::string> inputJsonPath = parser.string("input")
        .required()
        .help("Path to input json");

    maps::cmdline::Option<std::string> publishedJsonPath = parser.string("accepted_output")
        .required()
        .help("Path to output json with published buildings");

    maps::cmdline::Option<std::string> errorJsonPath = parser.string("error_output")
        .required()
        .help("Path to output json with buildings with errors");

    parser.parse(argc, const_cast<char**>(argv));

    json::Value inputResults = json::Value::fromFile(inputJsonPath);

    std::ofstream publishedOfs(publishedJsonPath);
    REQUIRE(publishedOfs.is_open(), "Failed to open file: " + publishedJsonPath);
    std::ofstream errorOfs(errorJsonPath);
    REQUIRE(errorOfs.is_open(), "Failed to open file: " + errorJsonPath);

    publishedOfs << "[";
    errorOfs << "[";

    json::Builder publishedBuilder(publishedOfs);
    json::Builder errorBuilder(errorOfs);

    for (const json::Value& resultJson : inputResults) {
        PublicationResult result = PublicationResult::fromJson(resultJson);
        if (PublicationStatus::Published == result.status) {
            publishedBuilder << [&](json::ObjectBuilder b) {
                result.toJson(b);
            };
        } else {
            errorBuilder << [&](json::ObjectBuilder b) {
                result.toJson(b);
            };
        }
    }

    publishedOfs << "]";
    errorOfs << "]";

    publishedOfs.close();
    errorOfs.close();

    return EXIT_SUCCESS;
}
catch (const maps::Exception& e) {
    INFO() << e;
    return EXIT_FAILURE;
}
catch (const std::exception& e) {
    INFO() << e.what();
    return EXIT_FAILURE;
}
catch (...) {
    INFO() << "Caught unknown exception";
    return EXIT_FAILURE;
}
