#ifndef NETWORKMANAGER_H
#define NETWORKMANAGER_H

#include <QObject>
#include <QNetworkRequest>

QT_BEGIN_NAMESPACE
class QNetworkReply;
class QNetworkAccessManager;
class QJsonDocument;
QT_END_NAMESPACE

class NetworkManager : public QObject
{
  Q_OBJECT
public:
  static NetworkManager &instance();

  // Delete copy constructor and assignment
  NetworkManager(const NetworkManager &) = delete;
  void operator=(const NetworkManager &) = delete;

  QString sessionToken() const;

public slots:
  // Convenience methods that inject session token.
  // Network manager discard replies internally, in cases where a consumer callsite prefers to not manage QNetworkReply.
  QNetworkReply *get(const QString &path);
  QNetworkReply *post(const QString &path, const QJsonDocument &data);
  QNetworkReply *put(const QString &path, const QJsonDocument &data);
  QNetworkReply *patch(const QString &path, const QJsonDocument &data);
  QNetworkReply *del(const QString &path);
  QNetworkReply *del(const QString &path, const QJsonDocument &data);

  void ping();

  /// @brief Builds an authenticated QNetworkRequest for the given path.
  /// Callers can further configure the request (e.g. redirect policy) before sending.
  QNetworkRequest buildRequest(const QString &path);

  /// @brief sets session token which will is injected into every request's headers
  void setSessionToken(const QString &token);

signals:
  /// @brief Emitted when a request is made and fails required authentication.
  void unauthorizedDetected();
  void pingResult(int ms);
  void pingFailed();

private:
  NetworkManager();
  ~NetworkManager();

  QString m_sessionToken;
  QNetworkAccessManager *m_qnam;

  void setAuthHeader(QNetworkRequest &request);
  /// @brief Combines the api url with given path
  /// @param path should be like "/auth/me"
  QString getFullUrl(const QString &path);
};

#endif // NETWORKMANAGER_H
