#pragma once

#include "lite_wallet_gateway.h"
#include "wallet_backend.h"
#include "wallet_capabilities.h"

#include <string>

namespace dragonx::wallet {

enum class LiteWalletRefreshRouteKind {
    FullNodeRpc,
    LiteGateway,
    Unavailable,
};

struct LiteWalletRefreshServiceOptions {
    bool allowLiteGatewayRefresh = false;
};

struct LiteWalletRefreshServicePlan {
    bool ok = false;
    LiteWalletRefreshRouteKind route = LiteWalletRefreshRouteKind::Unavailable;
    bool fullNodeRefreshDelegated = false;
    bool liteGatewayConfigured = false;
    bool liteGatewayExecutionAllowed = false;
    LiteWalletRefreshPlan liteGatewayPlan;
    WalletBackendStatus status;
    std::string error;
};

struct LiteWalletRefreshServiceResult {
    bool ok = false;
    bool attempted = false;
    bool fullNodeRefreshDelegated = false;
    bool liteGatewayCalled = false;
    LiteWalletRefreshServicePlan plan;
    LiteWalletRefreshResult liteGatewayResult;
    LiteWalletRefreshBundle bundle;
    WalletBackendStatus status;
    std::string error;
};

class LiteWalletRefreshGateway {
public:
    virtual ~LiteWalletRefreshGateway() = default;

    virtual LiteWalletRefreshPlan planRefresh(const LiteWalletRefreshRequest& request) const = 0;
    virtual LiteWalletRefreshResult refresh(const LiteWalletRefreshRequest& request) = 0;
    virtual WalletBackendStatus status() const = 0;
};

class LiteWalletGatewayRefreshAdapter final : public LiteWalletRefreshGateway {
public:
    explicit LiteWalletGatewayRefreshAdapter(LiteWalletGateway& gateway);

    LiteWalletRefreshPlan planRefresh(const LiteWalletRefreshRequest& request) const override;
    LiteWalletRefreshResult refresh(const LiteWalletRefreshRequest& request) override;
    WalletBackendStatus status() const override;

private:
    LiteWalletGateway& gateway_;
};

const char* liteWalletRefreshRouteKindName(LiteWalletRefreshRouteKind route);
LiteWalletRefreshRouteKind liteWalletRefreshRouteForCapabilities(const WalletCapabilities& capabilities);

class LiteWalletRefreshService {
public:
    LiteWalletRefreshService(WalletCapabilities capabilities,
                             LiteWalletRefreshGateway* liteGateway = nullptr,
                             LiteWalletRefreshServiceOptions options = {});

    const WalletCapabilities& capabilities() const { return capabilities_; }
    const LiteWalletRefreshServiceOptions& options() const { return options_; }

    LiteWalletRefreshRouteKind route() const;
    WalletBackendStatus status() const;
    LiteWalletRefreshServicePlan planRefresh(const LiteWalletRefreshRequest& request) const;
    LiteWalletRefreshServiceResult refresh(const LiteWalletRefreshRequest& request);

private:
    WalletBackendStatus statusForRoute(LiteWalletRefreshRouteKind route,
                                       const std::string& detail = {}) const;
    LiteWalletRefreshServiceResult resultFromPlan(const LiteWalletRefreshServicePlan& plan) const;

    WalletCapabilities capabilities_;
    LiteWalletRefreshGateway* liteGateway_ = nullptr;
    LiteWalletRefreshServiceOptions options_;
};

} // namespace dragonx::wallet