#include <saas/rtyserver_jupi/library/extbuilder/tester_lib.h>
#include <library/cpp/getopt/last_getopt.h>
#include <library/cpp/getopt/modchooser.h>
#include <library/cpp/logger/global/global.h>

using namespace NLastGetopt;

int main_run(int argc, const char** argv) {
    TOpts options = TOpts::Default();
    options.AddHelpOption();
    options.AddCharOption('i', "root dir for relative paths").OptionalArgument("PATH").Optional();
    options.AddCharOption('p', "operations to run (comma separated)").OptionalArgument("NAME").Optional();
    options.SetFreeArgsMin(1);
    options.SetFreeArgTitle(0, "prototext", "path to prototext file with NRtDoc::TBuilderTask");

    TOptsParseResult args(&options, argc, argv);

    TFsPath protoTextFile(args.GetFreeArgs()[0]);
    TString projectPath;

    if (args.Has('i')) {
        projectPath = args.Get<TString>('i');
        Y_ENSURE(TFsPath(projectPath).Exists());
    }

    THolder<NFusion::TPartialBundleConfig> filter;
    {
        TSet<TString> filterOperations;
        if (args.Has('p')) {
            TString value = args.Get<TString>('p');
            StringSplitter(value).Split(',').AddTo(&filterOperations);
        }
        if (filterOperations) {
            filter = MakeHolder<NFusion::TPartialBundleConfig>();
            filter->Exclusive = true;
            filter->DisplayNames = std::move(filterOperations);
        }
    }

    Y_ENSURE(protoTextFile.Exists());

    NRtDoc::TBuilderTask task;

    NFusion::RestoreBuilderTask(task, protoTextFile, projectPath);
    NFusion::TExtBuilderTaskDebug::MkDirs(task);

    NRtDoc::TBuilderTaskResult mergeResult;
    {
        NFusion::TAssertPolicy pol;
        pol.VerifyBundleDependencies_ = false;
        task.MutableConfig()->SetDisableShardsPrepare(filter && !filter->DisplayNames.contains("RunShardsPrepare"));
        NFusion::TExtBuilderTaskDebug t(task, &pol, std::move(filter));
        bool success = t.Run(mergeResult);
        if (!success && mergeResult.GetErrorCode() == 0) {
            mergeResult.SetErrorCode(-255);
        }
    }

    Y_ENSURE(mergeResult.GetErrorCode() == 0, "merge failed with return code " << mergeResult.GetErrorCode());
    return EXIT_SUCCESS;
}

int main(int argc, const char** argv) {
    InitGlobalLog2Console(TLOG_DEBUG);
    TModChooser modChooser;
    modChooser.AddMode("run", main_run, "Run full merge routine");
    int rc;
    try {
        rc = modChooser.Run(argc, argv);
    } catch (...) {
        Cerr << "ERROR: " << CurrentExceptionMessage() << Endl;
        rc = EXIT_FAILURE;
    }
    DEBUG_LOG << "RESOURCES on exit: " << NLoggingImpl::GetSystemResources() << Endl;
    Sleep(TDuration::Seconds(10)); // for memory profiler
    return rc;
}
