/**
 * Monero wallet balance using monero-javascript
 * Creates a view-only wallet from address + view key, syncs with daemon, returns balance.
 * Compatible with createPspMoneroWallet() output (address, viewKey).
 */
'use strict';

const monerojs = require('monero-javascript');

// Public Monero mainnet daemons (no auth)
const DEFAULT_DAEMON_URI = 'http://node.moneroworld.com:18081';
const DEFAULT_NETWORK = 'mainnet';

/**
 * Get wallet balance using monero-javascript view-only wallet.
 * Syncs with the blockchain and returns balance in atomic units and XMR.
 *
 * @param {string} address - Monero primary address
 * @param {string} viewKey - Private view key (hex)
 * @param {object} options - Optional settings
 * @param {string} options.serverUri - Daemon URI (default: public node)
 * @param {string} options.networkType - 'mainnet'|'stagenet'|'testnet'
 * @param {number} options.restoreHeight - Block height to start scanning (default: 0)
 * @returns {Promise<{balance: bigint, unlockedBalance: bigint, balanceXmr: number, unlockedBalanceXmr: number}>}
 */
async function getBalanceFromViewKey(address, viewKey, options = {}) {
    const serverUri = options.serverUri || DEFAULT_DAEMON_URI;
    const networkType = options.networkType || DEFAULT_NETWORK;
    const restoreHeight = options.restoreHeight ?? 0;

    // Create in-memory view-only wallet (path: "" or omit for memory-only)
    let wallet = null;
    try {
        wallet = await monerojs.createWalletFull({
            path: '',  // In-memory wallet - no disk
            password: '',
            networkType,
            primaryAddress: address,
            privateViewKey: viewKey,
            restoreHeight,
            proxyToWorker: false,  // Required in Node: worker uses browser URL scheme and fails
            server: {
                uri: serverUri,
                username: options.serverUsername || '',
                password: options.serverPassword || ''
            }
        });

        // Sync with the daemon
        await wallet.sync();

        const balance = await wallet.getBalance();
        const unlockedBalance = await wallet.getUnlockedBalance();
        const balanceStr = balance != null ? String(balance) : '0';
        const unlockedStr = unlockedBalance != null ? String(unlockedBalance) : '0';

        // Convert to XMR (1 XMR = 1e12 atomic units)
        const balanceXmr = Number(balanceStr) / 1e12;
        const unlockedBalanceXmr = Number(unlockedStr) / 1e12;

        return {
            balance: BigInt(balanceStr),
            unlockedBalance: BigInt(unlockedStr),
            balanceXmr,
            unlockedBalanceXmr
        };
    } finally {
        if (wallet) {
            try {
                await wallet.close(false);
            } catch (e) {
                console.warn('Wallet close:', e.message);
            }
        }
    }
}

/**
 * Same as getBalanceFromViewKey but returns MyMonero-API-compatible format
 * for drop-in replacement: total_received, total_sent, balance (atomic units).
 */
async function getBalanceMyMoneroFormat(address, viewKey, options = {}) {
    const result = await getBalanceFromViewKey(address, viewKey, options);
    // MyMonero returns total_received, total_sent; we have net balance
    return {
        total_received: result.balance.toString(),
        total_sent: '0',
        balance: result.balance.toString(),
        unlocked_balance: result.unlockedBalance.toString(),
        balanceXmr: result.balanceXmr,
        unlocked_balanceXmr: result.unlockedBalanceXmr
    };
}

module.exports = {
    getBalanceFromViewKey,
    getBalanceMyMoneroFormat,
    DEFAULT_DAEMON_URI
};
