#include <fmt/format.h>
#include <string>
#include <string_view>
 
#include <userver/storages/secdist/provider_component.hpp>
 
namespace samples::redis {
 public:
  static constexpr std::string_view kName = "handler-script";
 
 
  std::string HandleRequestThrow(
 
 private:
 
  storages::redis::ClientPtr redis_client_;
  storages::redis::CommandControl redis_cc_;
};
 
 public:
  static constexpr std::string_view kName = "handler-key-value";
 
 
  std::string HandleRequestThrow(
 
 private:
  std::string GetValue(std::string_view key,
  std::string PostValue(std::string_view key,
  std::string DeleteValue(std::string_view key) const;
 
  storages::redis::ClientPtr redis_client_;
  storages::redis::CommandControl redis_cc_;
};
 
}  
 
namespace samples::redis {
 
    : server::handlers::HttpHandlerBase(config, context),
      redis_client_{
          context.FindComponent<
components::Redis>(
"key-value-database")
 
              .GetClient("taxi-tmp")},
      redis_cc_{
std::chrono::seconds{15}, 
std::chrono::seconds{60}, 4} {}
 
 
std::string KeyValue::HandleRequestThrow(
  const auto& key = request.
GetArg(
"key");
 
  if (key.empty()) {
  }
 
  switch (request.
GetMethod()) {
 
    case server::http::HttpMethod::kGet:
      return GetValue(key, request);
    case server::http::HttpMethod::kPost:
      return PostValue(key, request);
    case server::http::HttpMethod::kDelete:
      return DeleteValue(key);
    default:
          fmt::format("Unsupported method {}", request.GetMethod())});
  }
}
 
std::string KeyValue::GetValue(std::string_view key,
  const auto result = redis_client_->Get(std::string{key}, redis_cc_).Get();
  if (!result) {
    return {};
  }
  return *result;
}
 
std::string KeyValue::PostValue(
  const auto& value = request.
GetArg(
"value");
 
  const auto result =
      redis_client_->SetIfNotExist(std::string{key}, value, redis_cc_).Get();
  if (!result) {
    return {};
  }
 
  return std::string{value};
}
 
std::string KeyValue::DeleteValue(std::string_view key) const {
  const auto result = redis_client_->Del(std::string{key}, redis_cc_).Get();
  return std::to_string(result);
}
 
    : server::handlers::HttpHandlerBase(config, context),
      redis_client_{
          context.FindComponent<
components::Redis>(
"key-value-database")
 
              .GetClient("taxi-tmp")} {}
 
std::string EvalSha::HandleRequestThrow(
  const auto& command = request.
GetArg(
"command");
 
  if (command.empty()) {
  }
 
  if (command == "evalsha") {
    return EvalShaRequest(request);
  }
  if (command == "scriptload") {
    return ScriptLoad(request);
  }
      "Invalid 'command' query argument: must be 'evalsha' or 'scriptload'"});
}
 
std::string EvalSha::EvalShaRequest(
  const auto script_hash = request.
GetArg(
"hash");
 
  if (script_hash.empty()) {
  }
  const auto& key = request.
GetArg(
"key");
 
  if (key.empty()) {
  }
 
  auto redis_request =
      redis_client_->EvalSha<std::string>(script_hash, {key}, {}, redis_cc_);
  const auto eval_sha_result = redis_request.Get();
  if (eval_sha_result.HasValue()) {
    return eval_sha_result.Get();
  }
  if (eval_sha_result.IsNoScriptError()) {
    return "NOSCRIPT";
  }
 
}
 
std::string EvalSha::ScriptLoad(
  const auto script = request.
GetArg(
"script");
 
  if (script.empty()) {
  }
  const auto& key = request.
GetArg(
"key");
 
  if (key.empty()) {
  }
 
  const auto shard = redis_client_->ShardByKey(key);
  auto redis_request = redis_client_->ScriptLoad(script, shard, redis_cc_);
  return redis_request.Get();
}
}  
 
int main(int argc, char* argv[]) {
  const auto component_list =
          .
Append<samples::redis::KeyValue>()
 
          .Append<samples::redis::EvalSha>()
          .Append<components::DefaultSecdistProvider>()
          .Append<components::TestsuiteSupport>()
}