#pragma once

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

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

namespace dragonx::wallet {

enum class LiteWalletStateApplySection {
    ChainInfo,
    Height,
    Balance,
    Addresses,
    SpendableOutputs,
    Transactions,
    SyncStatus,
};

enum class LiteWalletStateApplyAction {
    Noop,
    SetField,
    ReplaceCollection,
    InspectOnly,
};

enum class LiteWalletStateApplyIssue {
    EmptyModel,
    IncompleteModel,
    AddressSpendabilityUnknown,
    SpendableOutputsHaveNoWalletStateTarget,
};

struct LiteWalletStateApplyIssueInfo {
    LiteWalletStateApplyIssue issue = LiteWalletStateApplyIssue::EmptyModel;
    std::string message;
};

struct LiteWalletStateApplyFieldPlan {
    LiteWalletStateApplySection section = LiteWalletStateApplySection::Balance;
    LiteWalletStateApplyAction action = LiteWalletStateApplyAction::Noop;
    std::string fieldName;
    std::string currentValue;
    std::string proposedValue;
    bool currentKnown = true;
    bool proposedKnown = true;
    bool wouldChange = false;
};

struct LiteWalletStateApplyCollectionPlan {
    LiteWalletStateApplySection section = LiteWalletStateApplySection::Addresses;
    LiteWalletStateApplyAction action = LiteWalletStateApplyAction::Noop;
    std::string collectionName;
    std::size_t currentCount = 0;
    std::size_t proposedCount = 0;
    bool hasWalletStateTarget = true;
    bool wouldReplace = false;
};

struct LiteWalletStateApplyPlan {
    bool ok = false;
    bool dryRunOnly = true;
    bool applyImplemented = false;
    bool stateMutationAllowed = false;
    bool wouldChangeWalletState = false;
    bool sourceComplete = false;

    bool hasChainInfo = false;
    bool hasHeight = false;
    bool hasBalance = false;
    bool hasAddresses = false;
    bool hasSpendableOutputs = false;
    bool hasTransactions = false;
    bool hasSyncStatus = false;

    std::vector<LiteWalletStateApplyFieldPlan> fieldPlans;
    std::vector<LiteWalletStateApplyCollectionPlan> collectionPlans;
    std::vector<LiteWalletStateApplyIssueInfo> issues;
    std::string error;
};

const char* liteWalletStateApplySectionName(LiteWalletStateApplySection section);
const char* liteWalletStateApplyActionName(LiteWalletStateApplyAction action);
const char* liteWalletStateApplyIssueName(LiteWalletStateApplyIssue issue);

LiteWalletStateApplyPlan planLiteWalletStateApply(const LiteWalletAppRefreshModel& model,
                                                  const dragonx::WalletState& state);

class LiteWalletStateApplyPlanner {
public:
    LiteWalletStateApplyPlan buildPlan(const LiteWalletAppRefreshModel& model,
                                       const dragonx::WalletState& state) const;
};

} // namespace dragonx::wallet