#pragma once

#include "lite_wallet_app_refresh_coordinator.h"

#include <cstdint>
#include <string>
#include <vector>

namespace dragonx::wallet {

enum class LiteWalletRefreshReadinessStatus {
    EligibleDryRun,
    CoordinatorRejected,
    UnsafeReport,
    WaitingForLifecycle,
    WaitingForSync,
    Stale,
};

enum class LiteWalletRefreshReadinessIssue {
    CoordinatorReportRejected,
    CoordinatorReportIncomplete,
    CoordinatorReportUnsafe,
    FullNodeRouteRejected,
    LifecycleNotReady,
    SyncNotReady,
    RefreshTimestampMissing,
    RefreshTimestampInFuture,
    RefreshStale,
    StaleRefreshAllowed,
};

struct LiteWalletRefreshFreshnessInput {
    bool haveSnapshotTime = false;
    std::uint64_t snapshotTimeSeconds = 0;
    std::uint64_t nowSeconds = 0;
};

struct LiteWalletRefreshReadinessInputs {
    bool lifecycleReady = false;
    WalletBackendStatus lifecycleStatus;
    bool syncReady = false;
    WalletBackendStatus syncStatus;
    LiteWalletRefreshFreshnessInput freshness;
};

struct LiteWalletRefreshReadinessPolicyOptions {
    bool requireLifecycleReady = true;
    bool requireSyncReady = true;
    bool requireFreshRefresh = true;
    bool allowStaleRefresh = false;
    std::uint64_t maxRefreshAgeSeconds = 120;
};

struct LiteWalletRefreshReadinessIssueInfo {
    LiteWalletRefreshReadinessIssue issue = LiteWalletRefreshReadinessIssue::CoordinatorReportRejected;
    std::string message;
};

struct LiteWalletRefreshReadinessResult {
    bool ok = false;
    bool eligibleForFutureUiRefresh = false;
    bool coordinatorReportAccepted = false;
    bool dryRunOnly = true;
    bool noNetwork = true;
    bool stateMutationRequested = false;
    bool stateMutationAllowed = false;
    bool stateMutated = false;
    bool walletStateWritten = false;
    bool lifecycleReady = false;
    bool syncReady = false;
    bool refreshFresh = false;
    bool refreshStale = false;
    bool staleRefreshAllowed = false;

    LiteWalletRefreshReadinessStatus status = LiteWalletRefreshReadinessStatus::CoordinatorRejected;
    LiteWalletRefreshRouteKind route = LiteWalletRefreshRouteKind::Unavailable;
    WalletBackendStatus lifecycleStatus;
    WalletBackendStatus syncStatus;
    std::uint64_t refreshAgeSeconds = 0;
    std::uint64_t maxRefreshAgeSeconds = 0;
    std::vector<LiteWalletRefreshReadinessIssueInfo> issues;
    std::string error;
};

const char* liteWalletRefreshReadinessStatusName(LiteWalletRefreshReadinessStatus status);
const char* liteWalletRefreshReadinessIssueName(LiteWalletRefreshReadinessIssue issue);

LiteWalletRefreshReadinessResult evaluateLiteWalletRefreshReadiness(
    const LiteWalletAppRefreshCoordinationResult& coordination,
    const LiteWalletRefreshReadinessInputs& inputs,
    LiteWalletRefreshReadinessPolicyOptions options = {});

class LiteWalletRefreshReadinessPolicy {
public:
    explicit LiteWalletRefreshReadinessPolicy(LiteWalletRefreshReadinessPolicyOptions options = {});

    LiteWalletRefreshReadinessResult evaluate(
        const LiteWalletAppRefreshCoordinationResult& coordination,
        const LiteWalletRefreshReadinessInputs& inputs) const;

private:
    LiteWalletRefreshReadinessPolicyOptions options_;
};

} // namespace dragonx::wallet