#include "common.h"

#include "env.h"

namespace NBalancerServer::NTesting {

TServerCallback GetOkCallback() {
    return [](THttpRequestEnv& env) {
        UNIT_ASSERT_VALUES_EQUAL(env.Method(), NSrvKernel::EMethod::GET);
        UNIT_ASSERT_VALUES_EQUAL(env.Path(), "/yandsearch");

        NSrvKernel::TResponse response(200, "Ok");
        response.Props().ContentLength = 2;

        auto reply = env.GetReplyTransport();

        reply->SendHead(std::move(response));
        reply->SendData(TStringBuf("OK"));
        reply->SendEof();

        return NSrvKernel::TError();
    };
}

TServerCallback GetEchoCallback() {
    return [](THttpRequestEnv& env) {
        NSrvKernel::TResponse response(200, "Ok");
        response.Props().ChunkedTransfer = true;

        UNIT_ASSERT_VALUES_EQUAL(env.Method(), NSrvKernel::EMethod::POST);

        auto reply = env.GetReplyTransport();
        reply->SendHead(std::move(response));
        reply->SendData(env.Body());
        reply->SendEof();

        return NSrvKernel::TError();
    };
}

TString Repeat(const TString& v, size_t n) {
    TString res;
    for (size_t i = 0; i < n; ++i) {
        res += v;
    }

    return res;
};

void SendRequest(THttpOutput& out, const TString& request, const TString& data, const TString& compression,
                 const TString& acceptEncoding)
{
    if (compression) {
        out.EnableBodyEncoding(true);
    }

    out << request << "\r\n";

    if (compression) {
        out << "Content-Encoding: " << compression << "\r\n";
    }

    if (acceptEncoding) {
        out << "Accept-Encoding: " << acceptEncoding << "\r\n";
    }

    out << "\r\n";

    out << data;

    out.Finish();
}

TRequestResult SendHttpRequest(TCont* cont, size_t port, const TString& request, const TString& data,
                               const TString& compression, const TString& acceptEncoding)
{
    TRawSocketIO io("localhost", port, cont, Now() + TDuration::Seconds(10));
    THttpOutput out(&io);

    NTesting::SendRequest(out, request, data, compression, acceptEncoding);
    io.Flush();

    THttpInput httpI(&io);

    UNIT_ASSERT_VALUES_EQUAL(ParseHttpRetCode(httpI.FirstLine()), 200);

    return {httpI.ReadAll(), httpI.ContentEncoded()};
}

TRequestResult SendHttpsRequest(TCont* cont, size_t sslPort, const TString& request, const TString& data,
                                const TString& compression, const TString& acceptEncoding)
{
    TRawSocketIO io("localhost", sslPort, cont, Now() + TDuration::Seconds(10));
    TOpenSslClientIO ssl(&io, &io);
    THttpOutput out(&ssl);

    NTesting::SendRequest(out, request, data, compression, acceptEncoding);

    ssl.Flush();
    io.Flush();

    THttpInput httpI(&ssl);

    UNIT_ASSERT_VALUES_EQUAL(ParseHttpRetCode(httpI.FirstLine()), 200);

    return {httpI.ReadAll(), httpI.ContentEncoded()};
}

}  // namespace NBalancerServer::NTesting

