#pragma once

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

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

namespace dragonx::wallet {

enum class LiteWalletGatewayCommand {
    Info,
    Height,
    Balance,
    Addresses,
    Notes,
    List,
};

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

struct LiteWalletGatewayRequest {
    LiteWalletGatewayCommand command = LiteWalletGatewayCommand::Info;
    std::string serverUrl;
};

struct LiteWalletGatewayPlan {
    bool ok = false;
    LiteWalletGatewayCommand command = LiteWalletGatewayCommand::Info;
    LiteServerEndpoint server;
    std::size_t serverIndex = 0;
    bool customServer = false;
    bool bridgeExecutionAllowed = false;
    std::string commandName;
    std::string args;
    std::string error;
};

struct LiteWalletGatewayCommandResult {
    bool ok = false;
    bool attempted = false;
    bool bridgeAccepted = false;
    LiteWalletGatewayPlan plan;
    LiteResultParserError parserError = LiteResultParserError::None;
    WalletBackendStatus status;
    std::string bridgeResponseRedacted = "<empty>";
    std::string error;

    LiteInfoResponse info;
    LiteHeightResponse height;
    LiteBalanceResponse balance;
    LiteAddressesResponse addresses;
    LiteNotesResponse notes;
    LiteTransactionsResponse transactions;
};

struct LiteWalletRefreshRequest {
    std::string serverUrl;
    bool includeInfo = true;
    bool includeHeight = true;
    bool includeBalance = true;
    bool includeAddresses = true;
    bool includeNotes = true;
    bool includeTransactions = true;
    bool haveSyncStatus = false;
    LiteSyncStatusResponse syncStatus;
};

struct LiteWalletRefreshPlan {
    bool ok = false;
    std::vector<LiteWalletGatewayPlan> commands;
    std::string error;
};

struct LiteWalletRefreshBundle {
    bool hasInfo = false;
    bool hasHeight = false;
    bool hasBalance = false;
    bool hasAddresses = false;
    bool hasNotes = false;
    bool hasTransactions = false;
    bool hasSyncStatus = false;
    bool complete = false;
    std::size_t successfulCommandCount = 0;

    LiteInfoResponse info;
    LiteHeightResponse height;
    LiteBalanceResponse balance;
    LiteAddressesResponse addresses;
    LiteNotesResponse notes;
    LiteTransactionsResponse transactions;
    LiteSyncStatusResponse syncStatus;
};

struct LiteWalletRefreshResult {
    bool ok = false;
    bool attempted = false;
    LiteWalletRefreshPlan plan;
    std::vector<LiteWalletGatewayCommandResult> commandResults;
    LiteWalletRefreshBundle bundle;
    WalletBackendStatus status;
    std::string error;
};

struct LiteWalletGatewayOptions {
    bool allowBridgeCalls = false;
};

const char* liteWalletGatewayCommandName(LiteWalletGatewayCommand command);
const char* liteWalletGatewayAvailabilityName(LiteWalletGatewayAvailability availability);

std::vector<LiteWalletGatewayCommand> liteWalletRefreshCommands(const LiteWalletRefreshRequest& request);
LiteWalletRefreshBundle assembleLiteWalletRefreshBundle(const std::vector<LiteWalletGatewayCommandResult>& results,
                                                        const LiteWalletRefreshRequest& request);

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

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

    LiteWalletGatewayAvailability availability() const;
    WalletBackendStatus status() const;

    LiteWalletGatewayPlan planCommand(const LiteWalletGatewayRequest& request) const;
    LiteWalletRefreshPlan planRefresh(const LiteWalletRefreshRequest& request) const;
    LiteWalletGatewayCommandResult fetchCommand(const LiteWalletGatewayRequest& request);
    LiteWalletRefreshResult refresh(const LiteWalletRefreshRequest& request);

private:
    LiteServerSelectionResult selectServerForRequest(const std::string& serverUrl) const;
    WalletBackendStatus statusFor(LiteWalletGatewayAvailability availability,
                                  const std::string& detail = {}) const;
    LiteWalletGatewayCommandResult blockedCommandResult(const LiteWalletGatewayPlan& plan,
                                                        const WalletBackendStatus& blockedStatus) const;
    LiteWalletGatewayCommandResult executePlannedCommand(const LiteWalletGatewayPlan& plan);
    LiteWalletGatewayCommandResult parseBridgeResponse(const LiteWalletGatewayPlan& plan,
                                                       const std::string& response) const;

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

} // namespace dragonx::wallet