

const require_CredoError = require('../../error/CredoError.js');
require('../../error/index.js');
const require_version = require('../../utils/version.js');
const require_updates = require('./updates.js');
const require_StorageUpdateService = require('./StorageUpdateService.js');
const require_StorageUpdateError = require('./error/StorageUpdateError.js');

//#region src/storage/migration/UpdateAssistant.ts
var UpdateAssistant = class {
	constructor(agent, updateConfig = require_updates.DEFAULT_UPDATE_CONFIG) {
		this.agent = agent;
		this.updateConfig = updateConfig;
		this.storageUpdateService = this.agent.dependencyManager.resolve(require_StorageUpdateService.StorageUpdateService);
	}
	async initialize() {
		if (this.agent.isInitialized) throw new require_CredoError.CredoError("Can't initialize UpdateAssistant after agent is initialized");
	}
	async isUpToDate(updateToVersion) {
		return this.storageUpdateService.isUpToDate(this.agent.context, updateToVersion);
	}
	async getCurrentAgentStorageVersion() {
		return this.storageUpdateService.getCurrentStorageVersion(this.agent.context);
	}
	static get frameworkStorageVersion() {
		return require_updates.CURRENT_FRAMEWORK_STORAGE_VERSION;
	}
	async getNeededUpdates(toVersion) {
		const currentStorageVersion = require_version.parseVersionString(await this.storageUpdateService.getCurrentStorageVersion(this.agent.context));
		const parsedToVersion = toVersion ? require_version.parseVersionString(toVersion) : void 0;
		if (parsedToVersion && (require_version.isFirstVersionHigherThanSecond(currentStorageVersion, parsedToVersion) || require_version.isFirstVersionEqualToSecond(currentStorageVersion, parsedToVersion))) return [];
		const neededUpdates = require_updates.supportedUpdates.filter((update) => {
			const updateToVersion = require_version.parseVersionString(update.toVersion);
			if (parsedToVersion && require_version.isFirstVersionHigherThanSecond(updateToVersion, parsedToVersion)) return false;
			return require_version.isFirstVersionHigherThanSecond(updateToVersion, currentStorageVersion);
		});
		if (neededUpdates.length > 0 && require_version.isFirstVersionHigherThanSecond(require_version.parseVersionString(neededUpdates[0].fromVersion), currentStorageVersion)) throw new require_CredoError.CredoError(`First fromVersion is higher than current storage version. You need to use an older version of the framework to update to at least version ${neededUpdates[0].fromVersion}`);
		const lastUpdateToVersion = neededUpdates.length > 0 ? neededUpdates[neededUpdates.length - 1].toVersion : void 0;
		if (toVersion && lastUpdateToVersion && lastUpdateToVersion !== toVersion) throw new require_CredoError.CredoError(`No update found for toVersion ${toVersion}. Make sure the toVersion is a valid version you can update to`);
		return neededUpdates;
	}
	async update(options) {
		const updateIdentifier = Date.now().toString();
		const updateToVersion = options?.updateToVersion;
		try {
			this.agent.config.logger.info(`Starting update of agent storage with updateIdentifier ${updateIdentifier}`);
			const neededUpdates = await this.getNeededUpdates(updateToVersion);
			const currentStorageVersion = require_version.parseVersionString(await this.storageUpdateService.getCurrentStorageVersion(this.agent.context));
			const parsedToVersion = updateToVersion ? require_version.parseVersionString(updateToVersion) : void 0;
			if (parsedToVersion && (require_version.isFirstVersionHigherThanSecond(currentStorageVersion, parsedToVersion) || require_version.isFirstVersionEqualToSecond(currentStorageVersion, parsedToVersion))) throw new require_StorageUpdateError.StorageUpdateError(`Can't update to version ${updateToVersion} because it is lower or equal to the current agent storage version ${currentStorageVersion[0]}.${currentStorageVersion[1]}}`);
			if (neededUpdates.length === 0) {
				this.agent.config.logger.info("No update needed. Agent storage is up to date.");
				return;
			}
			const fromVersion = neededUpdates[0].fromVersion;
			const toVersion = neededUpdates[neededUpdates.length - 1].toVersion;
			this.agent.config.logger.info(`Starting update process. Total of ${neededUpdates.length} update(s) will be applied to update the agent storage from version ${fromVersion} to version ${toVersion}`);
			try {
				for (const update of neededUpdates) {
					const registeredModules = Object.values(this.agent.dependencyManager.registeredModules);
					const modulesWithUpdate = [];
					for (const registeredModule of registeredModules) {
						const moduleUpdate = registeredModule.updates?.find((module$1) => module$1.fromVersion === update.fromVersion && module$1.toVersion === update.toVersion);
						if (moduleUpdate) modulesWithUpdate.push({
							module: registeredModule,
							update: moduleUpdate
						});
					}
					this.agent.config.logger.info(`Starting update of agent storage from version ${update.fromVersion} to version ${update.toVersion}. Found ${modulesWithUpdate.length} extension module(s) with update scripts`);
					await update.doUpdate(this.agent);
					this.agent.config.logger.info(`Finished update of core agent storage from version ${update.fromVersion} to version ${update.toVersion}. Starting update of extension modules`);
					for (const moduleWithUpdate of modulesWithUpdate) {
						this.agent.config.logger.info(`Starting update of extension module ${moduleWithUpdate.module.constructor.name} from version ${moduleWithUpdate.update.fromVersion} to version ${moduleWithUpdate.update.toVersion}`);
						await moduleWithUpdate.update.doUpdate(this.agent, this.updateConfig);
						this.agent.config.logger.info(`Finished update of extension module ${moduleWithUpdate.module.constructor.name} from version ${moduleWithUpdate.update.fromVersion} to version ${moduleWithUpdate.update.toVersion}`);
					}
					await this.storageUpdateService.setCurrentStorageVersion(this.agent.context, update.toVersion);
					this.agent.config.logger.info(`Successfully updated agent storage from version ${update.fromVersion} to version ${update.toVersion}`);
				}
			} catch (error) {
				this.agent.config.logger.fatal("An error occurred while updating the wallet.", { error });
				throw error;
			}
		} catch (error) {
			this.agent.config.logger.error(`Error updating storage (updateIdentifier: ${updateIdentifier})`, { cause: error });
			throw new require_StorageUpdateError.StorageUpdateError(`Error updating storage (updateIdentifier: ${updateIdentifier}): ${error.message}`, { cause: error });
		}
		return updateIdentifier;
	}
};

//#endregion
exports.UpdateAssistant = UpdateAssistant;