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_DidCommConnectionService = require('../../connections/services/DidCommConnectionService.js');
const require_DidCommMediatorRoutingRecord = require('../repository/DidCommMediatorRoutingRecord.js');
const require_DidCommMediatorRoutingRepository = require('../repository/DidCommMediatorRoutingRepository.js');
const require_DidCommMessageSender = require('../../../DidCommMessageSender.js');
const require_DidCommConnectionMetadataTypes = require('../../connections/repository/DidCommConnectionMetadataTypes.js');
const require_DidCommRoutingEvents = require('../DidCommRoutingEvents.js');
const require_DidCommKeylistUpdateMessage = require('../messages/DidCommKeylistUpdateMessage.js');
const require_DidCommKeylistUpdateResponseMessage = require('../messages/DidCommKeylistUpdateResponseMessage.js');
const require_DidCommMediationGrantMessage = require('../messages/DidCommMediationGrantMessage.js');
require('../messages/index.js');
const require_DidCommMediationRole = require('../models/DidCommMediationRole.js');
const require_DidCommMediationState = require('../models/DidCommMediationState.js');
const require_DidCommMediationRecord = require('../repository/DidCommMediationRecord.js');
const require_DidCommMediationRepository = require('../repository/DidCommMediationRepository.js');
require('../../connections/services/index.js');
const require_DidCommMessagePickupApi = require('../../message-pickup/DidCommMessagePickupApi.js');
const require_DidCommMessagePickupSession = require('../../message-pickup/DidCommMessagePickupSession.js');
require('../../message-pickup/index.js');
const require_DidCommMessageForwardingStrategy = require('../DidCommMessageForwardingStrategy.js');
const require_DidCommMediatorModuleConfig = require('../DidCommMediatorModuleConfig.js');
require('../repository/index.js');
let __credo_ts_core = require("@credo-ts/core");
__credo_ts_core = require_rolldown_runtime.__toESM(__credo_ts_core);

//#region ../didcomm/src/modules/routing/services/DidCommMediatorService.ts
var _ref, _ref2, _ref3, _ref4;
let DidCommMediatorService = class DidCommMediatorService$1 {
	constructor(mediationRepository, mediatorRoutingRepository, eventEmitter, logger, connectionService) {
		this.mediationRepository = mediationRepository;
		this.mediatorRoutingRepository = mediatorRoutingRepository;
		this.eventEmitter = eventEmitter;
		this.logger = logger;
		this.connectionService = connectionService;
	}
	async getRoutingKeys(agentContext) {
		const mediatorRoutingRecord = await this.findMediatorRoutingRecord(agentContext);
		if (mediatorRoutingRecord) {
			this.logger.debug(`Returning mediator routing keys ${mediatorRoutingRecord.routingKeys}`);
			return mediatorRoutingRecord.routingKeysWithKeyId;
		}
		throw new __credo_ts_core.CredoError("Mediator has not been initialized yet.");
	}
	async processForwardMessage(messageContext) {
		const { message, agentContext } = messageContext;
		const messagePickupApi = agentContext.resolve(require_DidCommMessagePickupApi.DidCommMessagePickupApi);
		if (!message.to) throw new __credo_ts_core.CredoError("Invalid Message: Missing required attribute \"to\"");
		const mediationRecord = await this.mediationRepository.getSingleByRecipientKey(agentContext, message.to);
		mediationRecord.assertReady();
		mediationRecord.assertRole(require_DidCommMediationRole.DidCommMediationRole.Mediator);
		const connection = await this.connectionService.getById(agentContext, mediationRecord.connectionId);
		connection.assertReady();
		const messageForwardingStrategy = agentContext.dependencyManager.resolve(require_DidCommMediatorModuleConfig.DidCommMediatorModuleConfig).messageForwardingStrategy;
		const messageSender = agentContext.dependencyManager.resolve(require_DidCommMessageSender.DidCommMessageSender);
		switch (messageForwardingStrategy) {
			case require_DidCommMessageForwardingStrategy.DidCommMessageForwardingStrategy.QueueOnly:
				await messagePickupApi.queueMessage({
					connectionId: mediationRecord.connectionId,
					recipientDids: [(0, __credo_ts_core.verkeyToDidKey)(message.to)],
					message: message.message
				});
				break;
			case require_DidCommMessageForwardingStrategy.DidCommMessageForwardingStrategy.QueueAndLiveModeDelivery: {
				await messagePickupApi.queueMessage({
					connectionId: mediationRecord.connectionId,
					recipientDids: [(0, __credo_ts_core.verkeyToDidKey)(message.to)],
					message: message.message
				});
				const session = await messagePickupApi.getLiveModeSession({
					connectionId: mediationRecord.connectionId,
					role: require_DidCommMessagePickupSession.DidCommMessagePickupSessionRole.MessageHolder
				});
				if (session) await messagePickupApi.deliverMessagesFromQueue({
					pickupSessionId: session.id,
					recipientDid: (0, __credo_ts_core.verkeyToDidKey)(message.to)
				});
				break;
			}
			case require_DidCommMessageForwardingStrategy.DidCommMessageForwardingStrategy.DirectDelivery: await messageSender.sendPackage(agentContext, {
				connection,
				recipientKey: (0, __credo_ts_core.verkeyToDidKey)(message.to),
				encryptedMessage: message.message
			});
		}
	}
	async processKeylistUpdateRequest(messageContext) {
		const connection = messageContext.assertReadyConnection();
		const { message } = messageContext;
		const keylist = [];
		const mediationRecord = await this.mediationRepository.getByConnectionId(messageContext.agentContext, connection.id);
		mediationRecord.assertReady();
		mediationRecord.assertRole(require_DidCommMediationRole.DidCommMediationRole.Mediator);
		const connectionUsesDidKey = message.updates.some((update) => (0, __credo_ts_core.isDidKey)(update.recipientKey));
		await this.updateUseDidKeysFlag(messageContext.agentContext, connection, require_DidCommKeylistUpdateMessage.DidCommKeylistUpdateMessage.type.protocolUri, connectionUsesDidKey);
		for (const update of message.updates) {
			const updated = new require_DidCommKeylistUpdateResponseMessage.DidCommKeylistUpdated({
				action: update.action,
				recipientKey: update.recipientKey,
				result: require_DidCommKeylistUpdateResponseMessage.DidCommKeylistUpdateResult.NoChange
			});
			const publicKeyBase58 = (0, __credo_ts_core.didKeyToVerkey)(update.recipientKey);
			if (update.action === require_DidCommKeylistUpdateMessage.DidCommKeylistUpdateAction.add) {
				mediationRecord.addRecipientKey(publicKeyBase58);
				updated.result = require_DidCommKeylistUpdateResponseMessage.DidCommKeylistUpdateResult.Success;
				keylist.push(updated);
			} else if (update.action === require_DidCommKeylistUpdateMessage.DidCommKeylistUpdateAction.remove) {
				updated.result = mediationRecord.removeRecipientKey(publicKeyBase58) ? require_DidCommKeylistUpdateResponseMessage.DidCommKeylistUpdateResult.Success : require_DidCommKeylistUpdateResponseMessage.DidCommKeylistUpdateResult.NoChange;
				keylist.push(updated);
			}
		}
		await this.mediationRepository.update(messageContext.agentContext, mediationRecord);
		return new require_DidCommKeylistUpdateResponseMessage.DidCommKeylistUpdateResponseMessage({
			keylist,
			threadId: message.threadId
		});
	}
	async createGrantMediationMessage(agentContext, mediationRecord) {
		mediationRecord.assertState(require_DidCommMediationState.DidCommMediationState.Requested);
		mediationRecord.assertRole(require_DidCommMediationRole.DidCommMediationRole.Mediator);
		await this.updateState(agentContext, mediationRecord, require_DidCommMediationState.DidCommMediationState.Granted);
		const didcommConfig = agentContext.dependencyManager.resolve(require_DidCommModuleConfig.DidCommModuleConfig);
		const useDidKey = didcommConfig.useDidKeyInProtocols;
		const routingKeys = (await this.getRoutingKeys(agentContext)).map((routingKey) => useDidKey ? new __credo_ts_core.DidKey(routingKey).did : __credo_ts_core.TypedArrayEncoder.toBase58(routingKey.publicKey.publicKey));
		return {
			mediationRecord,
			message: new require_DidCommMediationGrantMessage.DidCommMediationGrantMessage({
				endpoint: didcommConfig.endpoints[0],
				routingKeys,
				threadId: mediationRecord.threadId
			})
		};
	}
	async processMediationRequest(messageContext) {
		const mediationRecord = new require_DidCommMediationRecord.DidCommMediationRecord({
			connectionId: messageContext.assertReadyConnection().id,
			role: require_DidCommMediationRole.DidCommMediationRole.Mediator,
			state: require_DidCommMediationState.DidCommMediationState.Requested,
			threadId: messageContext.message.threadId
		});
		await this.mediationRepository.save(messageContext.agentContext, mediationRecord);
		this.emitStateChangedEvent(messageContext.agentContext, mediationRecord, null);
		return mediationRecord;
	}
	async findById(agentContext, mediatorRecordId) {
		return this.mediationRepository.findById(agentContext, mediatorRecordId);
	}
	async getById(agentContext, mediatorRecordId) {
		return this.mediationRepository.getById(agentContext, mediatorRecordId);
	}
	async getAll(agentContext) {
		return await this.mediationRepository.getAll(agentContext);
	}
	async findMediatorRoutingRecord(agentContext) {
		return await this.mediatorRoutingRepository.findById(agentContext, this.mediatorRoutingRepository.MEDIATOR_ROUTING_RECORD_ID);
	}
	async createMediatorRoutingRecord(agentContext) {
		const kms = agentContext.resolve(__credo_ts_core.Kms.KeyManagementApi);
		const didcommConfig = agentContext.resolve(require_DidCommModuleConfig.DidCommModuleConfig);
		const routingKey = await kms.createKey({ type: {
			kty: "OKP",
			crv: "Ed25519"
		} });
		const publicJwk = __credo_ts_core.Kms.PublicJwk.fromPublicJwk(routingKey.publicJwk);
		const routingRecord = new require_DidCommMediatorRoutingRecord.DidCommMediatorRoutingRecord({
			id: this.mediatorRoutingRepository.MEDIATOR_ROUTING_RECORD_ID,
			routingKeys: [{
				routingKeyFingerprint: publicJwk.fingerprint,
				kmsKeyId: routingKey.keyId
			}]
		});
		try {
			await this.mediatorRoutingRepository.save(agentContext, routingRecord);
			this.eventEmitter.emit(agentContext, {
				type: require_DidCommRoutingEvents.DidCommRoutingEventTypes.RoutingCreatedEvent,
				payload: { routing: {
					endpoints: didcommConfig.endpoints,
					routingKeys: [],
					recipientKey: routingKey
				} }
			});
		} catch (error) {
			if (error instanceof __credo_ts_core.RecordDuplicateError) return this.mediatorRoutingRepository.getById(agentContext, this.mediatorRoutingRepository.MEDIATOR_ROUTING_RECORD_ID);
			throw error;
		}
		return routingRecord;
	}
	async findAllByQuery(agentContext, query, queryOptions) {
		return await this.mediationRepository.findByQuery(agentContext, query, queryOptions);
	}
	async updateState(agentContext, mediationRecord, newState) {
		const previousState = mediationRecord.state;
		mediationRecord.state = newState;
		await this.mediationRepository.update(agentContext, mediationRecord);
		this.emitStateChangedEvent(agentContext, mediationRecord, previousState);
	}
	emitStateChangedEvent(agentContext, mediationRecord, previousState) {
		this.eventEmitter.emit(agentContext, {
			type: require_DidCommRoutingEvents.DidCommRoutingEventTypes.MediationStateChanged,
			payload: {
				mediationRecord: mediationRecord.clone(),
				previousState
			}
		});
	}
	async updateUseDidKeysFlag(agentContext, connection, protocolUri, connectionUsesDidKey) {
		const useDidKeysForProtocol = connection.metadata.get(require_DidCommConnectionMetadataTypes.DidCommConnectionMetadataKeys.UseDidKeysForProtocol) ?? {};
		useDidKeysForProtocol[protocolUri] = connectionUsesDidKey;
		connection.metadata.set(require_DidCommConnectionMetadataTypes.DidCommConnectionMetadataKeys.UseDidKeysForProtocol, useDidKeysForProtocol);
		await this.connectionService.update(agentContext, connection);
	}
};
DidCommMediatorService = require_decorate.__decorate([
	(0, __credo_ts_core.injectable)(),
	require_decorateParam.__decorateParam(3, (0, __credo_ts_core.inject)(__credo_ts_core.InjectionSymbols.Logger)),
	require_decorateMetadata.__decorateMetadata("design:paramtypes", [
		typeof (_ref = typeof require_DidCommMediationRepository.DidCommMediationRepository !== "undefined" && require_DidCommMediationRepository.DidCommMediationRepository) === "function" ? _ref : Object,
		typeof (_ref2 = typeof require_DidCommMediatorRoutingRepository.DidCommMediatorRoutingRepository !== "undefined" && require_DidCommMediatorRoutingRepository.DidCommMediatorRoutingRepository) === "function" ? _ref2 : Object,
		typeof (_ref3 = typeof __credo_ts_core.EventEmitter !== "undefined" && __credo_ts_core.EventEmitter) === "function" ? _ref3 : Object,
		Object,
		typeof (_ref4 = typeof require_DidCommConnectionService.DidCommConnectionService !== "undefined" && require_DidCommConnectionService.DidCommConnectionService) === "function" ? _ref4 : Object
	])
], DidCommMediatorService);

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