/**
 * Send funds from a connected wallet to platform addresses (db.php).
 * Used by Receive (deposit) and Swap (pay-from-wallet).
 */
(function () {
    'use strict';

    const USDT_ERC20 = '0xdAC17F958D2ee523a2206206994597C13D831ec7';
    const USDT_TRC20 = 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t';
    const ERC20_ABI = [
        'function decimals() view returns (uint8)',
        'function transfer(address to, uint256 amount) returns (bool)'
    ];

    const CHAIN_PARAMS = {
        1: { chainId: '0x1', chainName: 'Ethereum', rpcUrls: ['https://rpc.ankr.com/eth'], nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 } },
        56: { chainId: '0x38', chainName: 'BNB Smart Chain', rpcUrls: ['https://bsc-dataseed.binance.org/'], nativeCurrency: { name: 'BNB', symbol: 'BNB', decimals: 18 } },
        137: { chainId: '0x89', chainName: 'Polygon', rpcUrls: ['https://polygon-rpc.com'], nativeCurrency: { name: 'MATIC', symbol: 'MATIC', decimals: 18 } }
    };

    function coinConfig(slug) {
        const map = {
            usdt_erc20: { type: 'erc20', chainId: 1, token: USDT_ERC20, decimals: 6 },
            eth: { type: 'native', chainId: 1 },
            bnb: { type: 'native', chainId: 56 },
            matic: { type: 'native', chainId: 137 },
            usdt_trc20: { type: 'trc20', token: USDT_TRC20, decimals: 6 },
            trx: { type: 'trx' }
        };
        return map[slug] || null;
    }

    async function switchChain(provider, chainId) {
        const hex = '0x' + Number(chainId).toString(16);
        try {
            await provider.request({ method: 'wallet_switchEthereumChain', params: [{ chainId: hex }] });
        } catch (err) {
            if (err && (err.code === 4902 || err.code === -32603) && CHAIN_PARAMS[chainId]) {
                await provider.request({ method: 'wallet_addEthereumChain', params: [CHAIN_PARAMS[chainId]] });
            } else {
                throw err;
            }
        }
    }

    async function ensureTron() {
        if (window.tronLink && window.tronLink.request) {
            try {
                await window.tronLink.request({ method: 'tron_requestAccounts' });
            } catch (e) {
                /* user may already be connected */
            }
        }
        if (window.tronWeb && window.tronWeb.defaultAddress && window.tronWeb.defaultAddress.base58) {
            return window.tronWeb;
        }
        throw new Error('Tron wallet not found. Open this page in TronLink or Trust Wallet to send TRC20 / TRX.');
    }

    async function sendEvm(cfg, toAddress, cryptoAmt) {
        if (!window.WalletHub) throw new Error('Wallet hub is not loaded.');
        const session = await WalletHub.ensureConnected();
        const provider = WalletHub.getProvider();
        if (provider && provider.request) {
            await switchChain(provider, cfg.chainId);
        }
        const ethersProvider = new ethers.providers.Web3Provider(provider || WalletHub.getEthersProvider().provider);
        const signer = ethersProvider.getSigner();
        const network = await ethersProvider.getNetwork();
        if (Number(network.chainId) !== Number(cfg.chainId)) {
            throw new Error('Please switch your wallet to the correct network and try again.');
        }

        let tx;
        if (cfg.type === 'erc20') {
            const token = new ethers.Contract(cfg.token, ERC20_ABI, signer);
            let decimals = cfg.decimals;
            try { decimals = await token.decimals(); } catch (e) { decimals = cfg.decimals || 18; }
            const amountUnits = ethers.utils.parseUnits(String(cryptoAmt), decimals);
            tx = await token.transfer(toAddress, amountUnits);
        } else {
            const value = ethers.utils.parseUnits(String(cryptoAmt), 18);
            tx = await signer.sendTransaction({ to: toAddress, value: value });
        }
        return { hash: tx.hash, wait: function () { return tx.wait(1); }, chainId: cfg.chainId };
    }

    async function sendTron(cfg, toAddress, cryptoAmt) {
        const tronWeb = await ensureTron();
        if (cfg.type === 'trx') {
            const sun = tronWeb.toSun(String(cryptoAmt));
            const tx = await tronWeb.trx.sendTransaction(toAddress, sun);
            const hash = tx.txid || tx.transaction || tx;
            return { hash: typeof hash === 'string' ? hash : (hash.txID || hash.txid), wait: async function () { await new Promise(function (r) { setTimeout(r, 2500); }); }, chainId: 728 };
        }
        const amount = Math.round(parseFloat(cryptoAmt) * Math.pow(10, cfg.decimals || 6));
        const contract = await tronWeb.contract().at(cfg.token);
        const hash = await contract.transfer(toAddress, amount).send();
        return { hash: hash, wait: async function () { await new Promise(function (r) { setTimeout(r, 2500); }); }, chainId: 728 };
    }

    async function recordAndConfirm(payload) {
        const rec = await fetch('api/wallet/record_deposit.php', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            credentials: 'same-origin',
            body: JSON.stringify(payload)
        });
        const recJson = await rec.json();
        if (!recJson.ok) throw new Error(recJson.error || 'Could not save deposit');

        for (let i = 0; i < 24; i++) {
            const check = await fetch('api/wallet/check_deposit.php?tx_hash=' + encodeURIComponent(payload.tx_hash), { credentials: 'same-origin' });
            const data = await check.json();
            if (data.status === 'confirmed') return data;
            if (data.status === 'failed') throw new Error('On-chain transfer could not be verified.');
            await new Promise(function (r) { setTimeout(r, 4000); });
        }
        return { status: 'pending' };
    }

    async function sendToPlatform(opts) {
        const coin = opts.coin;
        const toAddress = opts.toAddress;
        const cryptoAmount = opts.cryptoAmount;
        const usdAmount = opts.usdAmount;
        const purpose = opts.purpose || 'deposit';
        const creditCoin = opts.creditCoin || coin;

        if (!toAddress) throw new Error('Platform wallet address is missing for this asset.');
        const cfg = coinConfig(coin);
        if (!cfg) {
            throw new Error('This asset cannot be sent automatically. Copy the address and send from a compatible wallet.');
        }

        let sent;
        if (cfg.type === 'trc20' || cfg.type === 'trx') {
            sent = await sendTron(cfg, toAddress, cryptoAmount);
        } else {
            sent = await sendEvm(cfg, toAddress, cryptoAmount);
        }

        try { await sent.wait(); } catch (e) { /* still record; server will confirm */ }

        const verify = await recordAndConfirm({
            tx_hash: sent.hash,
            amount_usd: usdAmount,
            amount_crypto: cryptoAmount,
            coin: coin,
            credit_coin: creditCoin,
            purpose: purpose,
            chain_id: sent.chainId,
            recipient: toAddress
        });

        return { hash: sent.hash, verify: verify };
    }

    window.WalletFund = {
        sendToPlatform: sendToPlatform,
        coinConfig: coinConfig
    };
})();
