#include <library/cpp/testing/unittest/registar.h>

#include <balancer/kernel/custom_io/chunkio.h>
#include <balancer/modules/headers/handler.h>
#include <balancer/kernel/testing/conn_descr.h>
#include <balancer/kernel/testing/process_mock.h>

#include <library/cpp/regex/pire/regexp.h>

using namespace NSrvKernel;
using namespace NSrvKernel::NTesting;
using namespace NModHeaders;

/*
 * This unit test covers only a values generated by the create_func_(weak) function.
 */
Y_UNIT_TEST_SUITE(TModHeadersUnitTest) {
    const TChunkList REQUEST = TChunkList("GET / HTTP/1.1\r\nHOST: example.com\r\n\r\n");

    Y_UNIT_TEST(CreateYUid) {
        TProcessMock process;
        TTestConnDescr descr(process);

        descr.ConnDescr().Request->Headers().Add("X-Y-Uid", "x");

        THeadersHandler handler;
        handler.Create({"X-y-Uid", EHeaderFunc::Yuid, {}, ""}, false);
        handler.Apply(descr.ConnDescr().Request->Headers(), descr.ConnDescr(), {});

        auto headerValue = descr.ConnDescr().Request->Headers().GetFirstValue("X-Y-Uid");
        UNIT_ASSERT_EQUAL(headerValue, "1000000000");
    }

    /*
     *  The same as "create_func". Replace X-Req-Id with search request id
     *  and check if the value is valid.
     */
    Y_UNIT_TEST(CreateReqId) {
        TProcessMock process;
        TTestConnDescr descr(process);

        descr.ConnDescr().Request->Headers().Add("X-Req-Id", "x");

        THeadersHandler handler;
        handler.Create({"X-req-Id", EHeaderFunc::ReqId, {}, ""}, false);
        handler.Apply(descr.ConnDescr().Request->Headers(), descr.ConnDescr(), {});

        auto headerValue = descr.ConnDescr().Request->Headers().GetFirstValue("X-Req-Id");
        UNIT_ASSERT_EQUAL(headerValue, "0-0");
    }

    /*
     *  The same as "create_func". Replace X-Req-Id with market request id
     *  and check if the value is valid.
     */
    Y_UNIT_TEST(CreateMarketReqId) {
        TProcessMock process;
        TTestConnDescr descr(process);

        descr.ConnDescr().Request->Headers().Add("X-Req-Id", "x");

        THeadersHandler handler;
        handler.Create({"X-req-Id", EHeaderFunc::MarketReqId, {}, ""}, false);
        handler.Apply(descr.ConnDescr().Request->Headers(), descr.ConnDescr(), {});

        auto headerValue = descr.ConnDescr().Request->Headers().GetFirstValue("X-Req-Id");
        UNIT_ASSERT_EQUAL(headerValue, "0/00000000000000000000000000000000");
    }

    /*
     *  The same as "create_func". Replace X-Req-Id with adfox request id
     *  and check if the value is valid.
     */
    Y_UNIT_TEST(CreateAdfoxReqId) {
        TProcessMock process;
        TTestConnDescr descr(process);

        descr.ConnDescr().Request->Headers().Add("X-Req-Id", "x");

        THeadersHandler handler;
        handler.Create({"X-req-Id", EHeaderFunc::AdfoxReqId, {}, ""}, false);
        handler.Apply(descr.ConnDescr().Request->Headers(), descr.ConnDescr(), {});

        auto headerValue = descr.ConnDescr().Request->Headers().GetFirstValue("X-Req-Id");
        UNIT_ASSERT_EQUAL(headerValue, "0");
    }

    /*
     *  Check if append uses '/' delimiter for MarketReqId
     */
    Y_UNIT_TEST(AppendMarketReqIdDelimiter) {
        TProcessMock process;
        TTestConnDescr descr(process);

        descr.ConnDescr().Request->Headers().Add("X-Req-Id", "x");

        THeadersHandler handler;
        handler.Append({"X-req-Id", EHeaderFunc::MarketReqId, {}, ""}, false);
        handler.Apply(descr.ConnDescr().Request->Headers(), descr.ConnDescr(), {});

        auto headerValue = descr.ConnDescr().Request->Headers().GetFirstValue("X-Req-Id");
        UNIT_ASSERT_EQUAL(headerValue, "x/0/00000000000000000000000000000000");
    }

    /*
     *  Check if append uses ', ' as default delimiter
     */
    Y_UNIT_TEST(AppendDefaultDelimiter) {
        TProcessMock process;
        TTestConnDescr descr(process);

        descr.ConnDescr().Request->Headers().Add("X-Req-Id", "x");

        THeadersHandler handler;
        handler.Append({"X-req-Id", EHeaderFunc::ReqId, {}, ""}, false);
        handler.Apply(descr.ConnDescr().Request->Headers(), descr.ConnDescr(), {});

        auto headerValue = descr.ConnDescr().Request->Headers().GetFirstValue("X-Req-Id");
        UNIT_ASSERT_EQUAL(headerValue, "x, 0-0");
    }

    /*
     *  Check if delimiter param has priority over default delimiter
     */
    Y_UNIT_TEST(AppendPriorityMarketReqIdDelimiter) {
        TProcessMock process;
        TTestConnDescr descr(process);

        descr.ConnDescr().Request->Headers().Add("X-Req-Id", "x");

        THeadersHandler handler;
        handler.Append({"X-req-Id", EHeaderFunc::MarketReqId, {}, "!"}, false);
        handler.Apply(descr.ConnDescr().Request->Headers(), descr.ConnDescr(), {});

        auto headerValue = descr.ConnDescr().Request->Headers().GetFirstValue("X-Req-Id");
        UNIT_ASSERT_EQUAL(headerValue, "x!0/00000000000000000000000000000000");
    }
}
