#pragma once

#include <QJsonObject>
#include <QObject>
#include <QString>
#include <functional>

class QNetworkAccessManager;

// Результат авторизации — то, что подставляется в ${auth_*} аргументы запуска.
struct AuthResult
{
    bool ok = false;
    bool twoFactorRequired = false;
    QString error;

    QString playerName;     // ${auth_player_name}
    QString uuid;           // ${auth_uuid}, hex без дефисов
    QString accessToken;    // ${auth_access_token}
    QString clientToken;    // ${clientid}
    QString userType;       // ${user_type}: legacy / msa / ELYBY
};

// Yggdrasil-клиент Ely.by плюс офлайн-режим. Все сетевые методы асинхронные:
// колбэк вызывается один раз в потоке GUI.
class AuthService : public QObject
{
    Q_OBJECT

public:
    using Callback = std::function<void(const AuthResult &)>;

    explicit AuthService(QObject *parent = nullptr);

    // UUID выводится из ника так же, как это делает сам Minecraft в офлайне:
    // UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(UTF_8)).
    static AuthResult offline(const QString &nickname);

    // Случайный clientToken лаунчера — генерируется один раз на профиль.
    static QString generateClientToken();

    // Полный цикл: validate -> refresh -> authenticate. password можно оставить
    // пустым, если уже есть рабочий accessToken.
    void loginElyBy(const QString &login,
                    const QString &password,
                    const QString &clientToken,
                    const QString &accessToken,
                    Callback callback);

    // Повтор авторизации с одноразовым кодом двухфакторки (пароль:код).
    void loginElyByWithTotp(const QString &login,
                            const QString &password,
                            const QString &totp,
                            const QString &clientToken,
                            Callback callback);

    // Скачивает authlib-injector в targetDir, если его там ещё нет.
    // Колбэк получает путь к jar либо текст ошибки.
    void ensureAuthlibInjector(const QString &targetDir,
                               std::function<void(const QString &path, const QString &error)> callback);

signals:
    void progress(const QString &message);

private:
    void postJson(const QString &endpoint,
                  const QJsonObject &body,
                  std::function<void(int status, const QJsonObject &response, const QString &transportError)> handler);

    void authenticate(const QString &login,
                      const QString &password,
                      const QString &clientToken,
                      Callback callback);

    QNetworkAccessManager *m_network;
};
