#pragma once

#include <QDateTime>
#include <QHash>
#include <QList>
#include <QObject>
#include <QString>
#include <QUrl>

#include <functional>
#include <optional>

class QNetworkAccessManager;
class QJsonObject;

// Одна строка манифеста Mojang.
struct RemoteVersionEntry
{
    QString id;                 // 1.21.8, 25w33a, b1.7.3
    QString type;               // release | snapshot | old_beta | old_alpha
    QUrl url;                   // <id>.json с описанием версии
    QString sha1;               // контрольная сумма самого json
    QDateTime releaseTime;
};

// Каталог версий Mojang: скачивает манифест, кэширует его в папке лаунчера и
// отдаёт из кэша, пока тот не устарел. Работает в GUI-потоке, как AuthService.
class VersionManifestService : public QObject
{
    Q_OBJECT

public:
    // ok = true и непустой warning — данные отдали из устаревшего кэша.
    using Callback = std::function<void(bool ok, const QString &warning)>;

    explicit VersionManifestService(QObject *parent = nullptr);

    QList<RemoteVersionEntry> versions() const { return m_versions; }
    bool hasData() const { return !m_versions.isEmpty(); }
    bool isRefreshing() const { return m_refreshing; }
    QDateTime fetchedAt() const { return m_fetchedAt; }

    // Запись по id — из неё установщик берёт ссылку на описание версии.
    std::optional<RemoteVersionEntry> find(const QString &id) const;

    // Единственная точка входа. Свежий кэш — колбэк отложенно, иначе один
    // сетевой запрос на всех, кто успел попросить.
    void ensureLoaded(Callback callback, bool forceRefresh = false);

signals:
    void versionsChanged();
    void refreshingChanged();

private:
    bool readCache();
    void writeCache();
    void startRefresh();
    void finishRefresh(bool ok, const QString &warning);
    void applyVersions(QList<RemoteVersionEntry> list);

    QNetworkAccessManager *m_network;
    QList<RemoteVersionEntry> m_versions;
    QHash<QString, int> m_indexById;
    QDateTime m_fetchedAt;
    bool m_refreshing = false;
    bool m_cacheRead = false;
    QList<Callback> m_pending;
};
