import base64 from '@root/encoding/base64.js';
import { Script } from '@ts-bitcoin/core';
import cbor from 'cbor';
import * as jose from 'jose';
import { cbor2jose, jose2cbor } from '../../cbor-jose.js';
import * as lzma from '../../lzma.js';
import { JWKOrHexKeyToCryptoKeyAndJWK, JWKToUncompressedHex } from '../../utils.js';
export class PeppolV1 {
    static PROTOCOL_ID = 'mB:peppol';
    createOptions;
    parseOptions;
    info;
    constructor(options) {
        this.createOptions = options.create;
        this.parseOptions = options.parse;
        this.info = options.info;
    }
    static async create(options) {
        const { jwk: pubKeyJWK } = await JWKOrHexKeyToCryptoKeyAndJWK(options.pubKey, 'ECDH', 'p256');
        const importedPubKey = await jose.importJWK(pubKeyJWK, 'ECDH-ES');
        const payload = await cbor.encodeAsync([options.value, options.options?.extra]);
        const compressed = await lzma.compress(payload, 9);
        const l0 = await new jose.GeneralEncrypt(compressed)
            .setProtectedHeader({ enc: 'A256GCM' })
            .addRecipient(importedPubKey)
            .setUnprotectedHeader({ alg: 'ECDH-ES+A256KW' })
            .encrypt();
        const cl0 = await jose2cbor(l0);
        let final = cl0;
        if (options.signingKey) {
            const _l1 = await new jose.GeneralSign(cl0);
            const { jwk, cryptoKey } = await JWKOrHexKeyToCryptoKeyAndJWK(options.signingKey, 'ECDSA', 'p256');
            const kid = await jose.calculateJwkThumbprint(jwk);
            _l1.addSignature(cryptoKey).setProtectedHeader({ alg: 'ES256', kid: kid });
            const l1 = await _l1.sign();
            final = await jose2cbor(l1);
        }
        const uncompressedPublicKey = JWKToUncompressedHex(pubKeyJWK);
        const info = {
            type: 'peppol',
            version: 1,
            options: {
                extra: options.options?.extra,
            },
            pubKey: uncompressedPublicKey,
            value: options.value,
            encryptedData: final,
        };
        return new PeppolV1({ create: options, parse: null, info: info });
    }
    static async parse(options) {
        const { data, privateKey, verifyKey } = options;
        const importedPrivateKey = await jose.importJWK(privateKey, 'ECDH-ES');
        const l1 = await cbor2jose(data);
        let l0;
        if ('ciphertext' in l1) {
            l0 = l1;
        }
        else if ('signatures' in l1) {
            // Optionally verify
            if (verifyKey) {
                const l1verify = await jose.generalVerify(l1, await jose.importJWK(verifyKey, 'ES256'));
                l0 = await cbor2jose(l1verify.payload);
            }
            else {
                // Signature present but not choosing to verify
                l0 = await cbor2jose(base64.base64ToBuf(l1.payload));
            }
        }
        const l0decrypted = await jose.generalDecrypt(l0, importedPrivateKey, {});
        const l0decrypteddata = l0decrypted.plaintext;
        const decompressed = await lzma.decompress(l0decrypteddata);
        const [originaldata, extra] = cbor.decode(decompressed);
        const info = {
            type: 'peppol',
            encryptedData: data,
            options: {
                extra: extra,
            },
            pubKey: options.pubKey,
            value: originaldata,
            version: 1,
        };
        return new PeppolV1({ create: null, parse: options, info: info });
    }
    static async fromOpReturnScriptHex(script, options) {
        const s = Script.fromHex(script);
        return PeppolV1.parse({
            data: s.chunks[s.chunks.length - 2].buf,
            privateKey: options.privateKey,
            pubKey: s.chunks[s.chunks.length - 1].buf.toString('hex'),
            verifyKey: options.verifyKey,
        });
    }
    toOpReturnScriptHex() {
        const s = Script.fromSafeDataArray([
            Buffer.from(PeppolV1.PROTOCOL_ID),
            this.info.encryptedData,
            Buffer.from(this.info.pubKey),
        ]);
        return s.toHex();
    }
}
//# sourceMappingURL=v1.js.map