#pragma once

#include "data/wallet_state.h"
#include "lite_wallet_refresh_service.h"
#include "lite_wallet_state_apply_executor.h"
#include "lite_wallet_state_mapper.h"

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

namespace dragonx::wallet {

enum class LiteWalletAppRefreshCoordinationStatus {
    DryRunReported,
    Rejected,
    ApplyUnavailable,
};

enum class LiteWalletAppRefreshCoordinationIssue {
    RefreshResultFailed,
    FullNodeRefreshDelegated,
    MappingFailed,
    ApplyPlanFailed,
    ApplyExecutionRejected,
    StateMutationDisabled,
    StateMutationImplementationMissing,
};

struct LiteWalletAppRefreshCoordinatorOptions {
    LiteWalletStateApplyExecutorOptions executorOptions;
};

struct LiteWalletAppRefreshCoordinationIssueInfo {
    LiteWalletAppRefreshCoordinationIssue issue = LiteWalletAppRefreshCoordinationIssue::StateMutationDisabled;
    std::string message;
};

struct LiteWalletAppRefreshCoordinationResult {
    bool ok = false;
    bool refreshAccepted = false;
    bool refreshAttempted = false;
    bool fullNodeRefreshDelegated = false;
    bool liteGatewayCalled = false;
    bool mapped = false;
    bool planned = false;
    bool executionReported = false;
    bool dryRunOnly = true;
    bool noNetwork = true;
    bool stateMutationRequested = false;
    bool stateMutationAllowed = false;
    bool stateMutated = false;
    bool walletStateWritten = false;

    LiteWalletAppRefreshCoordinationStatus status = LiteWalletAppRefreshCoordinationStatus::Rejected;
    LiteWalletRefreshRouteKind route = LiteWalletRefreshRouteKind::Unavailable;
    WalletBackendStatus refreshStatus;

    std::size_t successfulCommandCount = 0;
    std::size_t mapIssueCount = 0;
    std::size_t fieldPlanCount = 0;
    std::size_t collectionPlanCount = 0;
    std::size_t plannedChangeCount = 0;
    std::size_t planIssueCount = 0;
    std::size_t executionIssueCount = 0;

    LiteWalletStateMapResult mapResult;
    LiteWalletStateApplyPlan applyPlan;
    LiteWalletStateApplyExecutionResult executionResult;
    std::vector<LiteWalletAppRefreshCoordinationIssueInfo> issues;
    std::string error;
};

const char* liteWalletAppRefreshCoordinationStatusName(
    LiteWalletAppRefreshCoordinationStatus status);
const char* liteWalletAppRefreshCoordinationIssueName(
    LiteWalletAppRefreshCoordinationIssue issue);

LiteWalletAppRefreshCoordinationResult coordinateLiteWalletAppRefresh(
    const LiteWalletRefreshServiceResult& refreshResult,
    const dragonx::WalletState& walletState,
    LiteWalletAppRefreshCoordinatorOptions options = {});

class LiteWalletAppRefreshCoordinator {
public:
    explicit LiteWalletAppRefreshCoordinator(LiteWalletAppRefreshCoordinatorOptions options = {});

    LiteWalletAppRefreshCoordinationResult coordinate(
        const LiteWalletRefreshServiceResult& refreshResult,
        const dragonx::WalletState& walletState) const;

private:
    LiteWalletAppRefreshCoordinatorOptions options_;
};

} // namespace dragonx::wallet