"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.processTokenLoad = processTokenLoad;
const uuid_1 = require("uuid");
const settlement_core_1 = require("@dbis/settlement-core");
const config_1 = require("../config");
const fineract_1 = require("../adapters/fineract");
const omnl_1 = require("../adapters/omnl");
const settlement_store_1 = require("../store/settlement-store");
async function processTokenLoad(input) {
    const cfg = (0, config_1.loadConfig)();
    const profile = (0, config_1.loadOfficeProfile)();
    const officeId = (0, config_1.settlementOfficeId)(input.officeId);
    const req = { ...input, officeId };
    const existing = settlement_store_1.settlementStore.getByIdempotencyKey(req.idempotencyKey);
    if (existing?.phase === 'SETTLED')
        return existing;
    const now = new Date().toISOString();
    let record = existing ?? {
        settlementId: (0, uuid_1.v4)(),
        idempotencyKey: req.idempotencyKey,
        phase: 'RECEIVED',
        request: {
            idempotencyKey: req.idempotencyKey,
            officeId,
            valueDate: now.slice(0, 10),
            currency: req.currency ?? 'USD',
            amount: req.amount,
            creditorIban: 'INTERNAL-M2-TOKEN-LOAD',
            beneficiaryName: req.recipientAddress,
            remittanceInfo: `M2 token load ${req.lineId} → ${req.symbol ?? req.tokenAddress ?? 'token'}`,
            moneyLayers: ['M2'],
            rail: 'INTERNAL',
            convertToCrypto: {
                enabled: true,
                targetChainId: 138,
                tokenLineId: req.lineId,
                recipientAddress: req.recipientAddress,
            },
        },
        errors: [],
        createdAt: now,
        updatedAt: now,
    };
    const advance = (phase, patch = {}) => {
        record = { ...record, phase, updatedAt: new Date().toISOString(), ...patch };
        settlement_store_1.settlementStore.save(record);
    };
    try {
        advance('VALIDATED');
        advance('VERBIAGE_ROLLED', {
            verbiageDocument: [
                `OMNL M2 fiat-backed token load`,
                `Office ${officeId} · line ${req.lineId}`,
                `Amount ${req.amount} · recipient ${req.recipientAddress}`,
                `GL ${settlement_core_1.GL_CODES.M2_BROAD} → ${settlement_core_1.GL_CODES.CRYPTO_TOKEN_LIABILITY}`,
            ].join('\n'),
        });
        const balances = await (0, fineract_1.fetchGlBalances)(officeId);
        const snap = (0, settlement_core_1.buildMoneySupplySnapshot)(officeId, balances);
        const { loadAmount, fullyBacked } = (0, settlement_core_1.m2FiatToTokenLoadAmount)(req.amount, snap.M2.broadMoney);
        if (!fullyBacked) {
            record.errors.push(`M2 backing insufficient (${loadAmount}/${req.amount})`);
            advance('FAILED');
            return record;
        }
        const amount = parseFloat(loadAmount) || 0;
        if (amount > 0) {
            const [debitGlId, creditGlId] = await Promise.all([
                (0, fineract_1.resolveGlAccountId)(profile.settlement.glM2 ?? settlement_core_1.GL_CODES.M2_BROAD),
                (0, fineract_1.resolveGlAccountId)(settlement_core_1.GL_CODES.CRYPTO_TOKEN_LIABILITY),
            ]);
            const je = await (0, fineract_1.postJournalEntry)({
                officeId,
                transactionDate: now.slice(0, 10),
                referenceNumber: req.idempotencyKey,
                comments: `M2 token load ${req.lineId}`,
                debits: [{ glAccountId: debitGlId, amount }],
                credits: [{ glAccountId: creditGlId, amount }],
            });
            advance('FINERACT_POSTED', { fineractJournalRef: String(je.resourceId) });
        }
        else {
            advance('FINERACT_POSTED');
        }
        advance('HYBX_RAIL_DISPATCHED');
        advance('ISO20022_ARCHIVED');
        const mint = await (0, omnl_1.requestTokenMint)({
            lineId: req.lineId,
            amount: loadAmount,
            recipient: req.recipientAddress,
            settlementRef: record.settlementId,
            dryRun: !cfg.production.allowChainMintExecute,
            symbol: req.symbol,
            tokenAddress: req.tokenAddress,
        });
        advance('CHAIN_MINT_REQUESTED', { chainTxHash: mint.txHash });
        advance('SETTLED');
        return record;
    }
    catch (err) {
        record.errors.push(err instanceof Error ? err.message : String(err));
        advance('FAILED');
        return record;
    }
}
