#include <search/web/core/rule.h>

#include <search/meta/context.h>
#include <saas/library/querydata/report.h>

#include <library/cpp/logger/global/global.h>
#include <library/cpp/json/json_reader.h>


namespace NSaas {
    class TKeyValue2QuerySearchRuleContext : public IRearrangeRuleContext {
    private:
        TString DefaultNamespace;
        bool IsMMetaRequest = false;

    private:
        void DoInitRuleParams(const TAdjustRuleParams& arp) override {
            IsMMetaRequest = arp.RequestFields.CgiParam.Has("ag") && arp.RequestFields.CgiParam.Has("g");
        }

        void DoRearrangeAfterFetch(TRearrangeParams& rearrangeParams) override {
            DefaultNamespace = LocalScheme()["Namespace"];

            if (!rearrangeParams.Current.Grouping) {
                WARNING_LOG << "Empty TRearrangeParams::Current" << Endl;
                return;
            }

            TMetaGrouping* grouping = rearrangeParams.Current.Grouping;
            TMetaSearchContext* ctx = rearrangeParams.Result->Context();
            if (!grouping || !ctx)
                return;

            NSaas::TQueryDataReportBuilder qdBuilder;
            TVector<TString> attrsToDel;

            for (size_t i = 0; i < grouping->Size(); i++) {
                TMetaGroup::TDocs& docs = grouping->GetMetaGroup(i).MetaDocs;
                for (size_t j = 0; j < docs.size(); j++) {
                    TMergedDoc& doc = docs[j];
                    const auto searchSource = ctx->GetClient(doc.Doc())->SearchSource();

                    if (IsMMetaRequest) {
                        TMergedDoc::TDocAttributes* mutAttrs = doc.MutableAttributes();
                        mutAttrs->Add("Service", searchSource->Group);
                        continue;
                    }

                    const TMergedDoc::TDocAttributes& attrs = doc.Attributes();
                    NSaas::TQueryDataReportBuilder::TDocData qdDocData = DefaultNamespace.empty() ? qdBuilder.AddDocumentMeta(TString(doc.Url()), searchSource->Group) : qdBuilder.AddDocumentDataSet(TString(doc.Url()), DefaultNamespace, "categflag/" + DefaultNamespace, NQueryData::KT_CATEG);

                    for (const auto& [key, values]: attrs.Range()) {
                        if (key == "MTime") {
                            continue;
                        }

                        if (key == "_Timestamp") {
                            ui64 ts = FromString(values.FrontOrEmpty());
                            qdDocData.AddTimestamp(ts);
                            continue;
                        }

                        TString value(values.FrontOrEmpty());

                        TString keyString{key};
                        qdDocData.Add(keyString, value);
                        attrsToDel.push_back(keyString);
                    }

                    TMergedDoc::TDocAttributes* mutAttrs = doc.MutableAttributes();
                    for (auto& attrName : attrsToDel) {
                        mutAttrs->Erase(attrName);
                    }
                }
            }

            if (!IsMMetaRequest) {
                rearrangeParams.InsertWorkedRule("debug", qdBuilder.GetFinalReport().SerializeAsString());
            }
        }
    };

    class TKeyValue2QuerySearchRule : public IRearrangeRule {
        IRearrangeRuleContext* DoConstructContext() const override {
            return new TKeyValue2QuerySearchRuleContext();
        }
    };
}

IRearrangeRule* CreateKV2QuerySearchRule(const TString&, const TSearchConfig&) {
    return new NSaas::TKeyValue2QuerySearchRule();
}

REGISTER_REARRANGE_RULE(QueryData, CreateKV2QuerySearchRule);
