const require_rolldown_runtime = require('../../../_virtual/rolldown_runtime.js');
const require_decorateMetadata = require('../../../_virtual/_@oxc-project_runtime@0.94.0/helpers/decorateMetadata.js');
const require_decorate = require('../../../_virtual/_@oxc-project_runtime@0.94.0/helpers/decorate.js');
const require_DidCommModuleConfig = require('./DidCommModuleConfig.js');
const require_decorateParam = require('../../../_virtual/_@oxc-project_runtime@0.94.0/helpers/decorateParam.js');
const require_DidCommDocumentService = require('./services/DidCommDocumentService.js');
const require_helpers = require('./modules/connections/services/helpers.js');
const require_DidCommOutOfBandRole = require('./modules/oob/domain/DidCommOutOfBandRole.js');
const require_DidCommOutOfBandRepository = require('./modules/oob/repository/DidCommOutOfBandRepository.js');
const require_outOfBandRecordMetadataTypes = require('./modules/oob/repository/outOfBandRecordMetadataTypes.js');
const require_DidCommForwardMessage = require('./modules/routing/messages/DidCommForwardMessage.js');
const require_DidCommMediatorRoutingRepository = require('./modules/routing/repository/DidCommMediatorRoutingRepository.js');
let __credo_ts_core = require("@credo-ts/core");
__credo_ts_core = require_rolldown_runtime.__toESM(__credo_ts_core);

//#region ../didcomm/src/DidCommEnvelopeService.ts
var _ref;
let DidCommEnvelopeService = class DidCommEnvelopeService$1 {
	constructor(logger, didcommDocumentService) {
		this.logger = logger;
		this.didcommDocumentService = didcommDocumentService;
	}
	async encryptDidcommV1Message(agentContext, message, recipientKeys, senderKey) {
		const kms = agentContext.dependencyManager.resolve(__credo_ts_core.Kms.KeyManagementApi);
		const contentEncryptionKey = kms.randomBytes({ length: 32 });
		const recipients = [];
		for (const recipientKey of recipientKeys) {
			let encryptedSender = void 0;
			if (senderKey) {
				const { encrypted: encrypted$2 } = await kms.encrypt({
					key: { keyAgreement: {
						algorithm: "ECDH-HSALSA20",
						externalPublicJwk: recipientKey.convertTo(__credo_ts_core.Kms.X25519PublicJwk).toJson()
					} },
					encryption: { algorithm: "XSALSA20-POLY1305" },
					data: __credo_ts_core.TypedArrayEncoder.fromString(__credo_ts_core.TypedArrayEncoder.toBase58(senderKey.publicKey.publicKey))
				});
				encryptedSender = __credo_ts_core.TypedArrayEncoder.toBase64URL(encrypted$2);
			}
			const { encrypted: encrypted$1, iv: iv$1 } = await kms.encrypt({
				key: { keyAgreement: {
					algorithm: "ECDH-HSALSA20",
					externalPublicJwk: recipientKey.convertTo(__credo_ts_core.Kms.X25519PublicJwk).toJson(),
					keyId: senderKey?.keyId
				} },
				data: contentEncryptionKey,
				encryption: { algorithm: "XSALSA20-POLY1305" }
			});
			recipients.push({
				encrypted_key: __credo_ts_core.TypedArrayEncoder.toBase64URL(encrypted$1),
				header: {
					kid: __credo_ts_core.TypedArrayEncoder.toBase58(recipientKey.publicKey.publicKey),
					iv: iv$1 ? __credo_ts_core.TypedArrayEncoder.toBase64URL(iv$1) : void 0,
					sender: encryptedSender
				}
			});
		}
		const protectedString = __credo_ts_core.JsonEncoder.toBase64URL({
			enc: "xchacha20poly1305_ietf",
			typ: "JWM/1.0",
			alg: senderKey ? "Authcrypt" : "Anoncrypt",
			recipients
		});
		const { encrypted, iv, tag } = await kms.encrypt({
			encryption: {
				algorithm: "C20P",
				aad: __credo_ts_core.TypedArrayEncoder.fromString(protectedString)
			},
			data: __credo_ts_core.JsonEncoder.toBuffer(message),
			key: { privateJwk: {
				kty: "oct",
				k: __credo_ts_core.TypedArrayEncoder.toBase64URL(contentEncryptionKey)
			} }
		});
		if (!iv || !tag) throw new __credo_ts_core.CredoError("Expected 'iv' and 'tag' to be defined");
		return {
			ciphertext: __credo_ts_core.TypedArrayEncoder.toBase64URL(encrypted),
			iv: __credo_ts_core.TypedArrayEncoder.toBase64URL(iv),
			tag: __credo_ts_core.TypedArrayEncoder.toBase64URL(tag),
			protected: protectedString
		};
	}
	async decryptDidcommV1Message(agentContext, encryptedMessage) {
		const kms = agentContext.dependencyManager.resolve(__credo_ts_core.Kms.KeyManagementApi);
		const protectedJson = __credo_ts_core.JsonEncoder.fromBase64(encryptedMessage.protected);
		const alg = protectedJson.alg;
		if (alg !== "Anoncrypt" && alg !== "Authcrypt") throw new __credo_ts_core.CredoError(`Unsupported pack algorithm: ${alg}`);
		if (protectedJson.enc !== "xchacha20poly1305_ietf") throw new __credo_ts_core.CredoError(`Unsupported enc algorithm: ${protectedJson.enc}`);
		let recipientKey = null;
		let recipient = null;
		for (const _recipient of protectedJson.recipients) {
			recipientKey = await this.extractOurRecipientKeyWithKeyId(agentContext, _recipient);
			if (recipientKey) recipient = _recipient;
		}
		if (!recipientKey || !recipient) throw new __credo_ts_core.CredoError("No corresponding recipient key found");
		if (alg === "Authcrypt" && (!recipient.header.sender || !recipient.header.iv)) throw new __credo_ts_core.CredoError("Sender and iv header values are required for Authcrypt");
		let senderPublicJwk = void 0;
		if (recipient.header.sender) {
			const { data } = await kms.decrypt({
				key: { keyAgreement: {
					algorithm: "ECDH-HSALSA20",
					keyId: recipientKey.keyId
				} },
				decryption: { algorithm: "XSALSA20-POLY1305" },
				encrypted: __credo_ts_core.TypedArrayEncoder.fromBase64(recipient.header.sender)
			});
			senderPublicJwk = __credo_ts_core.Kms.PublicJwk.fromPublicKey({
				crv: "Ed25519",
				kty: "OKP",
				publicKey: __credo_ts_core.TypedArrayEncoder.fromBase58(__credo_ts_core.TypedArrayEncoder.toUtf8String(data))
			});
		}
		const { data: contentEncryptionKey } = await kms.decrypt({
			decryption: {
				algorithm: "XSALSA20-POLY1305",
				iv: recipient.header.iv ? __credo_ts_core.TypedArrayEncoder.fromBase64(recipient.header.iv) : void 0
			},
			encrypted: __credo_ts_core.TypedArrayEncoder.fromBase64(recipient.encrypted_key),
			key: { keyAgreement: {
				algorithm: "ECDH-HSALSA20",
				keyId: recipientKey.keyId,
				externalPublicJwk: senderPublicJwk?.convertTo(__credo_ts_core.Kms.X25519PublicJwk).toJson()
			} }
		});
		const { data: message } = await kms.decrypt({
			decryption: {
				algorithm: "C20P",
				iv: __credo_ts_core.TypedArrayEncoder.fromBase64(encryptedMessage.iv),
				tag: __credo_ts_core.TypedArrayEncoder.fromBase64(encryptedMessage.tag),
				aad: __credo_ts_core.TypedArrayEncoder.fromString(encryptedMessage.protected)
			},
			key: { privateJwk: {
				kty: "oct",
				k: __credo_ts_core.TypedArrayEncoder.toBase64URL(contentEncryptionKey)
			} },
			encrypted: __credo_ts_core.TypedArrayEncoder.fromBase64(encryptedMessage.ciphertext)
		});
		return {
			plaintextMessage: __credo_ts_core.JsonEncoder.fromBuffer(message),
			senderKey: senderPublicJwk,
			recipientKey
		};
	}
	async packMessage(agentContext, payload, keys) {
		const didcommConfig = agentContext.dependencyManager.resolve(require_DidCommModuleConfig.DidCommModuleConfig);
		const { routingKeys, senderKey } = keys;
		let recipientKeys = keys.recipientKeys;
		const message = payload.toJSON({ useDidSovPrefixWhereAllowed: didcommConfig.useDidSovPrefixWhereAllowed });
		this.logger.debug(`Pack outbound message ${message["@type"]}`);
		let encryptedMessage = await this.encryptDidcommV1Message(agentContext, message, recipientKeys, senderKey);
		for (const routingKey of routingKeys) {
			const forwardMessage = new require_DidCommForwardMessage.DidCommForwardMessage({
				to: __credo_ts_core.TypedArrayEncoder.toBase58(recipientKeys[0].publicKey.publicKey),
				message: encryptedMessage
			});
			recipientKeys = [routingKey];
			this.logger.debug("Forward message created", forwardMessage);
			const forwardJson = forwardMessage.toJSON({ useDidSovPrefixWhereAllowed: didcommConfig.useDidSovPrefixWhereAllowed });
			encryptedMessage = await this.encryptDidcommV1Message(agentContext, forwardJson, [routingKey]);
		}
		this.logger.debug(`Packed outbound message ${message["@type"]}`, { routingKeys: routingKeys.map((routingKey) => routingKey.fingerprint) });
		return encryptedMessage;
	}
	async unpackMessage(agentContext, encryptedMessage) {
		return await this.decryptDidcommV1Message(agentContext, encryptedMessage);
	}
	async extractOurRecipientKeyWithKeyId(agentContext, recipient) {
		const kms = agentContext.resolve(__credo_ts_core.Kms.KeyManagementApi);
		const publicKey = __credo_ts_core.Kms.PublicJwk.fromPublicKey({
			kty: "OKP",
			crv: "Ed25519",
			publicKey: __credo_ts_core.TypedArrayEncoder.fromBase58(recipient.header.kid)
		});
		try {
			const { didDocument, keys } = await this.didcommDocumentService.resolveCreatedDidDocumentWithKeysByRecipientKey(agentContext, publicKey);
			const verificationMethod = didDocument.findVerificationMethodByPublicKey(publicKey);
			const kmsKeyId = keys?.find(({ didDocumentRelativeKeyId }) => verificationMethod.id.endsWith(didDocumentRelativeKeyId))?.kmsKeyId;
			agentContext.config.logger.debug(`Found did '${didDocument.id}' for recipient key '${publicKey.fingerprint}' for incoming didcomm message`);
			publicKey.keyId = kmsKeyId ?? publicKey.legacyKeyId;
			return publicKey;
		} catch (error) {
			const mediatorRoutingRepository = agentContext.dependencyManager.resolve(require_DidCommMediatorRoutingRepository.DidCommMediatorRoutingRepository);
			if (error instanceof __credo_ts_core.RecordNotFoundError) {
				const mediatorRoutingRecord = await mediatorRoutingRepository.findSingleByQuery(agentContext, { routingKeyFingerprints: [publicKey.fingerprint] });
				if (mediatorRoutingRecord) {
					agentContext.config.logger.debug(`Found mediator routing record with id '${mediatorRoutingRecord.id}' for recipient key '${publicKey.fingerprint}' for incoming didcomm message`);
					const routingKey = mediatorRoutingRecord.routingKeysWithKeyId.find((routingKey$1) => publicKey.equals(routingKey$1));
					if (!routingKey) throw new __credo_ts_core.CredoError(`Expected to find key with fingerprint '${publicKey.fingerprint}' in routing keys of mediator routing record '${mediatorRoutingRecord.id}'`);
					if (routingKey) return routingKey;
				}
				const outOfBandRecord = await agentContext.dependencyManager.resolve(require_DidCommOutOfBandRepository.DidCommOutOfBandRepository).findSingleByQuery(agentContext, { $or: [{
					role: require_DidCommOutOfBandRole.DidCommOutOfBandRole.Sender,
					recipientKeyFingerprints: [publicKey.fingerprint]
				}, {
					role: require_DidCommOutOfBandRole.DidCommOutOfBandRole.Receiver,
					recipientRoutingKeyFingerprint: publicKey.fingerprint
				}] });
				if (outOfBandRecord?.role === require_DidCommOutOfBandRole.DidCommOutOfBandRole.Sender) {
					agentContext.config.logger.debug(`Found out of band record with id '${outOfBandRecord.id}' and role '${outOfBandRecord.role}' for recipient key '${publicKey.fingerprint}' for incoming didcomm message`);
					for (const service of outOfBandRecord.outOfBandInvitation.getInlineServices()) {
						const _recipientKey = require_helpers.getResolvedDidcommServiceWithSigningKeyId(service, outOfBandRecord.invitationInlineServiceKeys).recipientKeys.find((recipientKey) => recipientKey.equals(publicKey));
						if (_recipientKey) return _recipientKey;
					}
				} else if (outOfBandRecord?.role === require_DidCommOutOfBandRole.DidCommOutOfBandRole.Receiver) {
					agentContext.config.logger.debug(`Found out of band record with id '${outOfBandRecord.id}' and role '${outOfBandRecord.role}' for recipient key '${publicKey.fingerprint}' for incoming didcomm message`);
					const recipieintRouting = outOfBandRecord.metadata.get(require_outOfBandRecordMetadataTypes.DidCommOutOfBandRecordMetadataKeys.RecipientRouting);
					if (recipieintRouting?.recipientKeyFingerprint === publicKey.fingerprint) {
						publicKey.keyId = recipieintRouting.recipientKeyId ?? publicKey.legacyKeyId;
						return publicKey;
					}
				}
				if (await kms.getPublicKey({ keyId: publicKey.legacyKeyId }).catch((error$1) => {
					if (error$1 instanceof __credo_ts_core.Kms.KeyManagementKeyNotFoundError) return null;
					throw error$1;
				})) {
					agentContext.config.logger.debug(`Found public key with legacy key id '${publicKey.legacyKeyId}' for recipient key '${publicKey.fingerprint}' for incoming didcomm message`);
					publicKey.keyId = publicKey.legacyKeyId;
					return publicKey;
				}
			}
		}
		return null;
	}
};
DidCommEnvelopeService = require_decorate.__decorate([
	(0, __credo_ts_core.injectable)(),
	require_decorateParam.__decorateParam(0, (0, __credo_ts_core.inject)(__credo_ts_core.InjectionSymbols.Logger)),
	require_decorateMetadata.__decorateMetadata("design:paramtypes", [Object, typeof (_ref = typeof require_DidCommDocumentService.DidCommDocumentService !== "undefined" && require_DidCommDocumentService.DidCommDocumentService) === "function" ? _ref : Object])
], DidCommEnvelopeService);

//#endregion
Object.defineProperty(exports, 'DidCommEnvelopeService', {
  enumerable: true,
  get: function () {
    return DidCommEnvelopeService;
  }
});