#include "absl/strings/match.h"
#include "http_response.hpp"

#include "logging.hpp"
#include "managed_store.hpp"
#include "utils/hex_utils.hpp"

#include <boost/algorithm/string/case_conv.hpp>
#include <nlohmann/json.hpp>

#ifdef UNIT_TEST_BUILD
#include "test/g3/mock_managed_store.hpp" // NOLINT
#endif

namespace crow
{

Response& Response::operator=(Response&& r) noexcept
{
    BMCWEB_LOG_DEBUG << "Moving response containers; this: " << this
                     << "; other: " << &r;
    if (this == &r)
    {
        return *this;
    }
    stringResponse = std::move(r.stringResponse);
    r.stringResponse.emplace(response_type{});
    jsonValue = std::move(r.jsonValue);

    for (const auto& [marker, timestamp] : r.markers)
    {
        markers.emplace(marker, timestamp);
    }

    // Only need to move completion handler if not already completed
    // Note, there are cases where we might move out of a Response object
    // while in a completion handler for that response object.  This check
    // is intended to prevent destructing the functor we are currently
    // executing from in that case.
    if (!r.completed)
    {
        completeRequestHandler = std::move(r.completeRequestHandler);
        r.completeRequestHandler = nullptr;
    }
    else
    {
        completeRequestHandler = nullptr;
    }
    completed = r.completed;
    isAliveHelper = std::move(r.isAliveHelper);
    r.isAliveHelper = nullptr;
    return *this;
}

void Response::clear()
{
    BMCWEB_LOG_DEBUG << this << " Clearing response containers";
    stringResponse.emplace(response_type{});
    jsonValue.clear();
    completed = false;
    expectedHash = std::nullopt;
}

std::string Response::computeEtag() const
{
    // Only set etag if this request succeeded
    if (result() != boost::beast::http::status::ok)
    {
        return "";
    }
    // and the json response isn't empty
    if (jsonValue.empty())
    {
        return "";
    }
    size_t hashval = std::hash<nlohmann::json>{}(jsonValue);
    return "\"" + intToHexString(hashval, 8) + "\"";
}

void Response::setHashAndHandleNotModified()
{
    // Can only hash if we have content that's valid
    if (jsonValue.empty() || result() != boost::beast::http::status::ok)
    {
        return;
    }
    size_t hashval = std::hash<nlohmann::json>{}(jsonValue);
    std::string hexVal = "\"" + intToHexString(hashval, 8) + "\"";
    addHeader(boost::beast::http::field::etag, hexVal);
    if (expectedHash && hexVal == *expectedHash)
    {
        jsonValue.clear();
        result(boost::beast::http::status::not_modified);
    }
}

void Response::end()
{
    std::string etag = computeEtag();
    if (!etag.empty())
    {
        addHeader(boost::beast::http::field::etag, etag);
    }
    if (completed)
    {
        BMCWEB_LOG_ERROR << this << " Response was ended twice";
        return;
    }
    completed = true;
    BMCWEB_LOG_DEBUG << this << " calling completion handler";
    if (completeRequestHandler)
    {
        BMCWEB_LOG_DEBUG << this << " completion handler was valid";
        completeRequestHandler(*this);
    }
}

void Response::setCompleteRequestHandler(
    std::function<void(Response&)>&& handler)
{
    completeRequestHandler = std::move(handler);
    BMCWEB_LOG_DEBUG << this << " setting completion handler"
                     << &completeRequestHandler;
    // Now that we have a new completion handler attached, we're no longer
    // complete
    completed = false;
}

std::function<void(Response&)> Response::releaseCompleteRequestHandler()
{
    BMCWEB_LOG_DEBUG << this << " releasing completion handler"
                     << &completeRequestHandler;
    std::function<void(Response&)> ret = completeRequestHandler;
    completeRequestHandler = nullptr;
    completed = true;
    return ret;
}

void Response::addTimetrace(const std::string& marker)
{
    if (managedStore::GetManagedObjectStore()->getConfig().timetrace)
    {
        std::chrono::high_resolution_clock::time_point now =
            std::chrono::high_resolution_clock::now();
        auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
                      now.time_since_epoch())
                      .count();
        markers[marker] = ms;
    }
}

void Response::startTimetrace(const std::string& block)
{
    addTimetrace("START_" + block);
}

void Response::endTimetrace(const std::string& block)
{
    addTimetrace("END_" + block);
}

void Response::requestStartTime(const std::string& uri)
{
    addTimetrace("REQUEST_" + uri);
}
void Response::requestEndTime()
{
    addTimetrace("REQUESTEND");
}

nlohmann::json Response::timetraceToJson()
{
    nlohmann::json jsonObj;
    if (managedStore::GetManagedObjectStore()->getConfig().timetrace)
    {

        nlohmann::json& hops = jsonObj["hops"];
        hops = nlohmann::json::array();
        for (const auto& [marker, timestamp] : markers)
        {
            if (absl::StrContains(marker, "START_"))
            {
                continue;
            }
            // process END_
            size_t pos = marker.find("END_");
            if (pos != std::string::npos)
            {
                // find the start and calculate the diff
                std::string block = marker.substr(pos + 4);
                auto startTime = markers["START_" + block];
                auto duration = timestamp - startTime;
                nlohmann::json::object_t hop;
                hop["id"] = boost::algorithm::to_lower_copy(block);
                hop["time_ms"] = duration;
                hops.emplace_back(std::move(hop));
            }
            else if (absl::StrContains(marker, "REQUEST_"))
            {
                size_t uriPos = marker.find("REQUEST_");
                std::string uri = marker.substr(uriPos + 8);
                jsonObj["uri"] = uri;
                jsonObj["starttime"] = timestamp;
            }
            else if (absl::StrContains(marker, "REQUESTEND"))
            {
                jsonObj["endtime"] = timestamp;
            }
        }
    }
    return jsonObj;
}
void Response::updateTraceInManagedStore()
{
    if (managedStore::GetManagedObjectStore()->getConfig().timetrace)
    {
        nlohmann::json jsonObj = timetraceToJson();
        managedStore::GetManagedObjectStore()->storeTimeTrace(jsonObj);
    }
}

} // namespace crow
