// DragonX Wallet - ImGui Edition
// Copyright 2024-2026 The Hush Developers
// Released under the GPLv3

#pragma once

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

#include <cstddef>
#include <string>
#include <vector>

namespace dragonx {
namespace wallet {

enum class LiteWalletLifecycleOperation {
    CreateNew,
    OpenExisting,
    RestoreFromSeed
};

enum class LiteWalletLifecycleAvailability {
    Ready,
    UnsupportedBuild,
    BackendUnavailable,
    BridgeUnavailable,
    BridgeCallsDisabled,
    NoUsableServer,
    RolloutDisabled   // runtime kill-switch / staged-rollout gate (see lite_rollout_policy.h)
};

enum class LitePrivateDataKind {
    SeedPhrase,
    Passphrase,
    WalletPath,
    BridgeResponse
};

struct LiteRedactedPrivateData {
    LitePrivateDataKind kind = LitePrivateDataKind::SeedPhrase;
    bool present = false;
    std::string redactedValue = "<empty>";
};

struct LiteWalletCreateRequest {
    bool dangerous = false;
    std::string serverUrl;
    std::string passphrase;
};

struct LiteWalletOpenRequest {
    bool dangerous = false;
    std::string serverUrl;
    std::string walletPath;
    std::string passphrase;
};

struct LiteWalletRestoreRequest {
    bool dangerous = false;
    std::string serverUrl;
    std::string seedPhrase;
    unsigned long long birthday = 0;
    unsigned long long account = 0;
    bool overwrite = false;
    std::string walletPath;
    std::string passphrase;
};

struct LiteWalletLifecyclePlan {
    bool ok = false;
    LiteWalletLifecycleOperation operation = LiteWalletLifecycleOperation::CreateNew;
    LiteServerEndpoint server;
    std::size_t serverIndex = 0;
    bool customServer = false;
    bool bridgeExecutionAllowed = false;
    std::vector<LiteRedactedPrivateData> privateData;
    std::string error;
};

struct LiteWalletLifecycleResult {
    bool ok = false;
    bool attempted = false;
    bool bridgeAccepted = false;
    bool walletReady = false;
    LiteWalletLifecycleOperation operation = LiteWalletLifecycleOperation::CreateNew;
    LiteWalletLifecyclePlan plan;
    WalletBackendStatus status;
    std::string bridgeResponseRedacted = "<empty>";
    std::string error;
};

struct LiteWalletLifecycleOptions {
    bool allowBridgeCalls = false;
    bool rolloutBlocked = false;       // runtime kill-switch / staged-rollout gate is blocking
    std::string rolloutMessage;        // user-facing reason when rolloutBlocked
};

const char* liteWalletLifecycleOperationName(LiteWalletLifecycleOperation operation);
const char* liteWalletLifecycleAvailabilityName(LiteWalletLifecycleAvailability availability);
const char* litePrivateDataKindName(LitePrivateDataKind kind);
std::string redactLitePrivateDataValue(const std::string& value);

class LiteWalletLifecycleService {
public:
    // bridge is NON-OWNING (the controller owns the single shared LiteClientBridge);
    // it must outlive this service. The lite backend is a global singleton and every
    // LiteClientBridge shuts it down on destruction, so services must not own one.
    LiteWalletLifecycleService(WalletCapabilities capabilities,
                               LiteConnectionSettings connectionSettings,
                               LiteClientBridge* bridge,
                               LiteWalletLifecycleOptions options = {});

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

    LiteWalletLifecycleAvailability availability() const;
    WalletBackendStatus status() const;

    LiteWalletLifecyclePlan planCreateWallet(const LiteWalletCreateRequest& request) const;
    LiteWalletLifecyclePlan planOpenWallet(const LiteWalletOpenRequest& request) const;
    LiteWalletLifecyclePlan planRestoreWallet(const LiteWalletRestoreRequest& request) const;

    LiteWalletLifecycleResult createWallet(const LiteWalletCreateRequest& request);
    LiteWalletLifecycleResult openWallet(const LiteWalletOpenRequest& request);
    LiteWalletLifecycleResult restoreWallet(const LiteWalletRestoreRequest& request);

private:
    LiteServerSelectionResult selectServerForRequest(const std::string& serverUrl) const;
    LiteWalletLifecyclePlan makePlan(LiteWalletLifecycleOperation operation,
                                     const std::string& serverUrl,
                                     std::vector<LiteRedactedPrivateData> privateData,
                                     const std::string& validationError = {}) const;
    WalletBackendStatus statusFor(LiteWalletLifecycleAvailability availability,
                                  const std::string& detail = {}) const;
    LiteWalletLifecycleResult executeCreate(const LiteWalletCreateRequest& request,
                                            const LiteWalletLifecyclePlan& plan);
    LiteWalletLifecycleResult executeOpen(const LiteWalletOpenRequest& request,
                                          const LiteWalletLifecyclePlan& plan);
    LiteWalletLifecycleResult executeRestore(const LiteWalletRestoreRequest& request,
                                             const LiteWalletLifecyclePlan& plan);
    LiteWalletLifecycleResult blockedResult(const LiteWalletLifecyclePlan& plan,
                                            const WalletBackendStatus& blockedStatus) const;
    LiteWalletLifecycleResult bridgeResult(const LiteWalletLifecyclePlan& plan,
                                           const WalletBackendStatus& successStatus,
                                           const LiteBridgeStringResult& bridgeCall) const;

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

} // namespace wallet
} // namespace dragonx