"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createVaultsController = createVaultsController;
const ethers_1 = require("ethers");
const SweepVaultModel_js_1 = require("../../infrastructure/database/models/SweepVaultModel.js");
const MnemonicWallet_js_1 = require("../../infrastructure/payments/MnemonicWallet.js");
const BalanceService_js_1 = require("../../infrastructure/payments/BalanceService.js");
const VaultTransferService_js_1 = require("../../infrastructure/payments/VaultTransferService.js");
const AdminPinService_js_1 = require("../../infrastructure/auth/AdminPinService.js");
function createVaultsController(config, cryptoBox) {
    const balanceService = new BalanceService_js_1.BalanceService(config);
    const transferService = new VaultTransferService_js_1.VaultTransferService(config, cryptoBox);
    return {
        list: async (_req, res) => {
            const vaults = await SweepVaultModel_js_1.SweepVaultModel.find().sort({ createdAt: -1 }).lean();
            res.json({
                data: vaults.map((v) => ({
                    id: v._id.toString(),
                    evmAddress: v.evmAddress,
                    tronAddress: v.tronAddress,
                    isActive: v.isActive,
                    createdAt: v.createdAt.toISOString()
                }))
            });
        },
        getById: async (req, res) => {
            const vault = await SweepVaultModel_js_1.SweepVaultModel.findById(req.params.id).lean();
            if (!vault) {
                res.status(404).json({ error: "Vault not found." });
                return;
            }
            const [evmNativeBalance, evmUsdtBalance, tronNativeBalance, tronUsdtBalance] = await Promise.all([
                getEvmNativeBalance(config, vault.evmAddress, "bsc").catch(() => "0"),
                getUsdtBalanceSafe(config, vault.evmAddress, "bsc"),
                getTronNativeBalance(config, vault.tronAddress).catch(() => "0"),
                getUsdtBalanceSafe(config, vault.tronAddress, "tron")
            ]);
            res.json({
                id: vault._id.toString(),
                evmAddress: vault.evmAddress,
                tronAddress: vault.tronAddress,
                isActive: vault.isActive,
                balances: {
                    evm: { native: evmNativeBalance, usdt: evmUsdtBalance },
                    tron: { native: tronNativeBalance, usdt: tronUsdtBalance }
                },
                createdAt: vault.createdAt.toISOString()
            });
        },
        create: async (_req, res) => {
            const wallet = (0, MnemonicWallet_js_1.generateVaultWallet)();
            const vault = await SweepVaultModel_js_1.SweepVaultModel.create({
                evmAddress: wallet.evmAddress,
                tronAddress: wallet.tronAddress,
                encryptedSeedPhrase: cryptoBox.encrypt(wallet.seedPhrase),
                keyReference: "local:aes-256-gcm",
                isActive: true
            });
            res.status(201).json({
                id: vault._id.toString(),
                evmAddress: wallet.evmAddress,
                tronAddress: wallet.tronAddress,
                isActive: true,
                createdAt: vault.createdAt.toISOString()
            });
        },
        decrypt: async (req, res) => {
            const { adminKey } = req.body;
            const isValidPin = adminKey ? await AdminPinService_js_1.AdminPinService.verifyPin(adminKey) : false;
            if (!isValidPin) {
                res.status(403).json({ error: "Invalid admin PIN." });
                return;
            }
            const vault = await SweepVaultModel_js_1.SweepVaultModel.findById(req.params.id).lean();
            if (!vault) {
                res.status(404).json({ error: "Vault not found." });
                return;
            }
            const seedPhrase = cryptoBox.decrypt(vault.encryptedSeedPhrase);
            res.json({
                id: vault._id.toString(),
                evmAddress: vault.evmAddress,
                tronAddress: vault.tronAddress,
                seedPhrase
            });
        },
        transfer: async (req, res) => {
            const { adminKey, network, token, toAddress, amount } = req.body;
            const isValidPin = adminKey ? await AdminPinService_js_1.AdminPinService.verifyPin(adminKey) : false;
            if (!isValidPin) {
                res.status(403).json({ error: "Invalid admin PIN." });
                return;
            }
            if (!network || !token || !toAddress || !amount) {
                res.status(400).json({ error: "Missing required fields: network, token, toAddress, amount." });
                return;
            }
            const vault = await SweepVaultModel_js_1.SweepVaultModel.findById(req.params.id).lean();
            if (!vault) {
                res.status(404).json({ error: "Vault not found." });
                return;
            }
            const fromAddress = network === "tron" ? vault.tronAddress : vault.evmAddress;
            const seedPhrase = cryptoBox.decrypt(vault.encryptedSeedPhrase);
            try {
                const result = await transferService.transfer(network, seedPhrase, fromAddress, toAddress, token, BigInt(amount));
                res.json({ txHash: result.txHash });
            }
            catch (error) {
                const message = error instanceof Error ? error.message : String(error);
                res.status(500).json({ error: message });
            }
        },
        delete: async (req, res) => {
            const { adminKey, force } = req.body;
            const isValidPin = adminKey ? await AdminPinService_js_1.AdminPinService.verifyPin(adminKey) : false;
            if (!isValidPin) {
                res.status(403).json({ error: "Invalid admin PIN." });
                return;
            }
            const vault = await SweepVaultModel_js_1.SweepVaultModel.findById(req.params.id).lean();
            if (!vault) {
                res.status(404).json({ error: "Vault not found." });
                return;
            }
            const [evmNativeBalance, evmUsdtBalance, tronNativeBalance, tronUsdtBalance] = await Promise.all([
                getEvmNativeBalance(config, vault.evmAddress, "bsc").catch(() => "0"),
                getUsdtBalanceSafe(config, vault.evmAddress, "bsc"),
                getTronNativeBalance(config, vault.tronAddress).catch(() => "0"),
                getUsdtBalanceSafe(config, vault.tronAddress, "tron")
            ]);
            const hasAssets = BigInt(evmNativeBalance) > 0n ||
                BigInt(evmUsdtBalance) > 0n ||
                BigInt(tronNativeBalance) > 0n ||
                BigInt(tronUsdtBalance) > 0n;
            if (hasAssets && !force) {
                res.status(409).json({
                    error: "Vault still contains assets. Use force=true to delete anyway.",
                    warning: "This vault has a non-zero balance. Deleting it does not move or recover any funds.",
                    balances: {
                        evm: { native: evmNativeBalance, usdt: evmUsdtBalance },
                        tron: { native: tronNativeBalance, usdt: tronUsdtBalance }
                    }
                });
                return;
            }
            await SweepVaultModel_js_1.SweepVaultModel.findByIdAndDelete(req.params.id);
            res.json({ message: "Vault deleted successfully.", id: req.params.id });
        }
    };
}
async function getEvmNativeBalance(config, address, network) {
    const networkConfig = config.paymentNetworks[network];
    if (!networkConfig)
        return "0";
    const provider = new ethers_1.ethers.JsonRpcProvider(networkConfig.rpcUrl);
    const balance = await provider.getBalance(address);
    return balance.toString();
}
async function getTronNativeBalance(config, address) {
    const { TronWeb } = await import("tronweb");
    const networkConfig = config.paymentNetworks.tron;
    if (!networkConfig)
        return "0";
    const tronWeb = new TronWeb({
        fullHost: networkConfig.fullHost,
        headers: networkConfig.apiKey ? { "TRON-PRO-API-KEY": networkConfig.apiKey } : undefined
    });
    return (await tronWeb.trx.getBalance(address)).toString();
}
async function getUsdtBalanceSafe(config, address, network) {
    const balanceService = new BalanceService_js_1.BalanceService(config);
    try {
        return await balanceService.getUsdtBalance(network, address);
    }
    catch {
        return "0";
    }
}
