#pragma once
#include <optional>
#include <string>
#include <string_view>
#include <thread>
#include <mw/http_server.hpp>
#include "delivery_store.hpp"
#include "key_store.hpp"
#include "runtime_state.hpp"
#include "subscription_store.hpp"
#include "telegram_client.hpp"
namespace telegrammer
{
/// Serves authenticated API routes and translates service errors to JSON.
class ApiServer : public mw::HTTPServer
{
public:
/// Construct an API server over the shared application components.
ApiServer(mw::IPSocketInfo listen_info, KeyStore& keys,
SubscriptionStore& subscriptions, DeliveryStore& deliveries,
TelegramApi& telegram, RuntimeState& state);
/// Stop the listener and join its serving thread during destruction.
~ApiServer();
/// Bind synchronously, then start serving requests in a joined thread.
mw::E<void> start();
/// Stop accepting requests without destroying component dependencies.
void stop();
/// Wait for the serving thread to finish.
void wait();
protected:
/// Register routes and common HTTP server limits.
void setup() override;
private:
mw::IPSocketInfo listen_info_;
KeyStore& keys_;
SubscriptionStore& subscriptions_;
DeliveryStore& deliveries_;
TelegramApi& telegram_;
RuntimeState& state_;
std::thread server_thread_;
bool authenticate(const Request& request, Response& response);
bool requireJson(const Request& request, Response& response);
std::optional<json> parseObject(const Request& request, Response& response);
std::optional<int64_t> ownerId(const Response& response) const;
static void writeSuccess(Response& response, const json& body,
int status = 200);
static void writeNoContent(Response& response);
static void writeError(Response& response, int status,
std::string_view code, std::string_view message,
std::optional<std::string_view> field =
std::nullopt,
std::optional<int> retry_after = std::nullopt);
static void writeError(Response& response, const mw::Error& error);
void send(const Request& request, Response& response);
void subscribe(const Request& request, Response& response);
void listSubscriptions(const Request& request, Response& response);
void deleteSubscription(const Request& request, Response& response);
void health(const Request& request, Response& response);
};
} // namespace telegrammer