import { Buff } from '@cmdcode/buff';
import { sha256 } from '@cmdcode/crypto-tools/hash';
import { create_txhex } from './tx.js';
import { now, sort_record } from './util.js';
import { DEFAULT_DEADLINE } from '../config.js';
import { init_vm } from '../vm/main.js';
import { get_path_names, get_path_vouts, get_proposal_id, } from './proposal.js';
const GET_INIT_CONTRACT = () => {
    return {
        activated: null,
        balance: 0,
        expires_at: null,
        pending: 0,
        settled: false,
        settled_at: null,
        spent: false,
        spent_at: null,
        spent_txid: null,
        status: 'published',
        txin_count: 0,
        vm_state: null
    };
};
export function create_contract(config, members, terms, signatures = []) {
    const { agent_fee, feerate, published, session } = config;
    const outputs = config.outputs ?? get_spend_templates(terms, [agent_fee]);
    const prop_id = config.prop_id ?? get_proposal_id(terms);
    const cid = config.cid ?? get_contract_id(prop_id, published, outputs);
    const subtotal = terms.value + agent_fee[0];
    const vout_size = outputs[0][1].length / 2;
    const txfee = vout_size * feerate;
    return sort_record({
        ...GET_INIT_CONTRACT(),
        ...session,
        agent_fee: agent_fee,
        cid: cid,
        deadline: get_deadline(terms, published),
        est_txfee: txfee,
        est_txsize: vout_size,
        feerate: feerate,
        members: members ?? [],
        moderator: config.moderator ?? null,
        outputs: outputs,
        prop_id: prop_id,
        pubkeys: signatures.map(e => e.slice(0, 64)),
        published: published,
        signatures: signatures,
        subtotal: subtotal,
        terms: terms,
        total: subtotal + txfee,
        updated_at: published,
        vout_size: vout_size
    });
}
export function get_contract_id(prop_id, published, templates) {
    const outhex = templates.map(e => e[1]).sort();
    const stamp = Buff.num(published, 4);
    const preimg = Buff.join([prop_id, stamp, ...outhex]);
    return sha256(preimg).hex;
}
export function activate_contract(contract, activated = now()) {
    const { cid, terms } = contract;
    const { duration, paths, programs, schedule } = terms;
    const expires_at = activated + duration;
    const pathnames = get_path_names(paths);
    const vm_state = init_vm({ activated, cid, pathnames, programs, schedule });
    return { ...contract, activated, expires_at, status: 'active', vm_state };
}
function get_deadline(proposal, published) {
    const { deadline, effective } = proposal;
    if (effective !== undefined) {
        return effective - published;
    }
    else {
        return published + (deadline ?? DEFAULT_DEADLINE);
    }
}
export function get_spend_templates(proposal, fees) {
    const { payments, paths } = proposal;
    const pathnames = get_path_names(paths);
    const pay_total = [...payments, ...fees];
    return pathnames.map(pathname => {
        const vout = get_path_vouts(pathname, paths, pay_total);
        const txhex = create_txhex(vout);
        return [pathname, txhex];
    });
}
