#include "helpers.h"

#include <mapreduce/yt/interface/errors.h>
#include <mapreduce/yt/interface/client.h>
#include <util/generic/strbuf.h>
#include <util/generic/string.h>
#include <util/string/subst.h>

namespace NErrorHelpers {
    constexpr TStringBuf EXCEPTION_MARKER = "uncaught exception:";

    TString CutYtJobOutput(const TString& s, size_t limit) {
        const size_t leftLimit = s.size() <= limit ? 0 : s.size() - limit;
        size_t exceptPos = s.find(EXCEPTION_MARKER, leftLimit);
        if (exceptPos == TString::npos) {
            exceptPos = leftLimit;
        }
        return s.substr(exceptPos);
    }

    TString& CutLongMessage(TString& s, size_t limit) {
        if (s.size() > limit) {
            s.resize(limit);
        }
        return s;
    }

    TString& MakeSingleLineShortMessage(TString& s, size_t limit) {
        SubstGlobal(CutLongMessage(s, limit), '\n', '\t');
        return s;
    }

    TMaybe<TString> GetFirstNonemptyStderr(const NYT::TOperationFailedError& error) {
        for (const auto& jobInfo : error.GetFailedJobInfo()) {
            if (!jobInfo.Stderr.Empty()) {
                return jobInfo.Stderr;
            }
        }
        return Nothing();
    }

    TString ComposeErrorMessage(NYT::IClientBasePtr client, const NYT::TOperationFailedError& error) {
        // output from all jobs might be too much so we take only the first
        TMaybe<TString> jobError = GetFirstNonemptyStderr(error);
        auto operation = client->AttachOperation(error.GetOperationId());
        return jobError.GetOrElse("Unrecognized error.") + "Operation link: " + operation->GetWebInterfaceUrl();
    }
}
