#pragma once

#include "lite_client_bridge.h"
#include "lite_connection_service.h"
#include "lite_result_parsers.h"
#include "wallet_backend.h"
#include "wallet_capabilities.h"

#include <cstddef>
#include <cstdint>
#include <string>

namespace dragonx::wallet {

enum class LiteSyncOperation {
    StartSync,
    PollSyncStatus,
};

enum class LiteSyncStartMode {
    Startup,
    Restore,
    Rescan,
    Recovery,
};

enum class LiteSyncAvailability {
    Ready,
    UnsupportedBuild,
    BackendUnavailable,
    BridgeUnavailable,
    BridgeCallsDisabled,
    NoUsableServer,
};

enum class LiteSyncRecoveryDecisionKind {
    KeepPolling,
    SyncComplete,
    Stuck,
    ReorgDetected,
    InvalidStatus,
};

struct LiteSyncStartRequest {
    LiteSyncStartMode mode = LiteSyncStartMode::Startup;
    std::string serverUrl;
    bool forceRescan = false;
    bool afterRestore = false;
};

struct LiteSyncStatusRequest {
    std::string serverUrl;
};

struct LiteSyncPlan {
    bool ok = false;
    LiteSyncOperation operation = LiteSyncOperation::StartSync;
    LiteSyncStartMode startMode = LiteSyncStartMode::Startup;
    LiteServerEndpoint server;
    std::size_t serverIndex = 0;
    bool customServer = false;
    bool bridgeExecutionAllowed = false;
    std::string command;
    std::string args;
    bool forceRescan = false;
    bool afterRestore = false;
    std::string error;
};

struct LiteSyncStartResult {
    bool ok = false;
    bool attempted = false;
    bool syncStarted = false;
    LiteSyncPlan plan;
    WalletBackendStatus status;
    std::string error;
};

struct LiteSyncStatusResult {
    bool ok = false;
    bool attempted = false;
    bool bridgeAccepted = false;
    LiteSyncPlan plan;
    LiteSyncStatusResponse syncStatus;
    LiteResultParserError parserError = LiteResultParserError::None;
    WalletBackendStatus status;
    std::string bridgeResponseRedacted = "<empty>";
    std::string error;
};

struct LiteSyncRecoveryInput {
    bool havePreviousSyncedBlocks = false;
    std::uint64_t previousSyncedBlocks = 0;
    std::uint64_t syncedBlocks = 0;
    std::uint64_t totalBlocks = 0;
    std::uint64_t stagnantPollCount = 0;
    std::uint64_t stagnantPollThreshold = 10;
};

struct LiteSyncRecoveryDecision {
    LiteSyncRecoveryDecisionKind kind = LiteSyncRecoveryDecisionKind::KeepPolling;
    bool shouldPollAgain = true;
    bool shouldClear = false;
    bool shouldRescan = false;
    bool shouldRestartSync = false;
    bool requiresUserAttention = false;
    std::string reason;
};

struct LiteSyncServiceOptions {
    bool allowSyncStatusBridgeCalls = false;
};

const char* liteSyncOperationName(LiteSyncOperation operation);
const char* liteSyncStartModeName(LiteSyncStartMode mode);
const char* liteSyncAvailabilityName(LiteSyncAvailability availability);
const char* liteSyncRecoveryDecisionKindName(LiteSyncRecoveryDecisionKind kind);

WalletBackendStatus walletStatusFromLiteSyncStatus(const LiteSyncStatusResponse& syncStatus);
LiteSyncRecoveryDecision evaluateLiteSyncRecovery(const LiteSyncRecoveryInput& input);

class LiteSyncService {
public:
    LiteSyncService(WalletCapabilities capabilities,
                    LiteConnectionSettings connectionSettings,
                    LiteClientBridge* bridge,
                    LiteSyncServiceOptions options = {});

    const WalletCapabilities& capabilities() const { return capabilities_; }
    const LiteConnectionSettings& connectionSettings() const { return connectionSettings_; }
    const LiteSyncServiceOptions& options() const { return options_; }

    LiteSyncAvailability availability() const;
    WalletBackendStatus status() const;

    LiteSyncPlan planStartSync(const LiteSyncStartRequest& request) const;
    LiteSyncPlan planSyncStatus(const LiteSyncStatusRequest& request) const;
    LiteSyncStartResult startSync(const LiteSyncStartRequest& request);
    LiteSyncStatusResult pollSyncStatus(const LiteSyncStatusRequest& request);

private:
    LiteServerSelectionResult selectServerForRequest(const std::string& serverUrl) const;
    LiteSyncPlan makePlan(LiteSyncOperation operation,
                          const std::string& serverUrl,
                          bool bridgeExecutionAllowed,
                          LiteSyncStartMode startMode,
                          bool forceRescan,
                          bool afterRestore) const;
    WalletBackendStatus statusFor(LiteSyncAvailability availability,
                                  const std::string& detail = {}) const;
    LiteSyncStartResult blockedStartResult(const LiteSyncPlan& plan,
                                           const WalletBackendStatus& blockedStatus) const;
    LiteSyncStatusResult blockedStatusResult(const LiteSyncPlan& plan,
                                             const WalletBackendStatus& blockedStatus) const;

    WalletCapabilities capabilities_;
    LiteConnectionSettings connectionSettings_;
    LiteClientBridge* bridge_ = nullptr;  // non-owning; owned by LiteWalletController
    LiteSyncServiceOptions options_;
};

} // namespace dragonx::wallet