/* eslint-disable no-console */
/* eslint-disable no-useless-escape */
/* eslint no-param-reassign: 1  */
const ran = false; // set to true to exclude migration
const name = 'Replace all hard coded links to old file ids in lesson.';

const mongoose = require('mongoose');

const { Schema } = mongoose;
const lessonsModel = require('../src/services/lesson/model.js');
const { FileModel } = require('../src/services/fileStorage/model.js');

mongoose.Promise = global.Promise;

const sanitizeObj = (obj) => {
	Object.keys(obj).forEach(key => obj[key] === undefined && delete obj[key]);
	return obj;
};

const convertDocument = (doc) => {
	const [refOwnerModel, owner,] = doc.key.split('/');

	const refOwnerModelMap = {
		users: 'user',
		courses: 'course',
	};

	// Props obsolete in new model
	const nullers = {
		_id: undefined,
		__v: undefined,
		key: undefined,
		path: undefined,
		schoolId: undefined,
		flatFileName: undefined,
		studentCanEdit: undefined,
		permissions: undefined,
	};

	return sanitizeObj({
		...doc,
		isDirectory: !doc.type,
		refOwnerModel: refOwnerModelMap[refOwnerModel] || refOwnerModel,
		owner,
		storageFileName: doc.flatFileName,
		...nullers,
	});
};

const permissionTypes = ['can-read', 'can-write'];

const oldFileSchema = new Schema({
	key: { type: String, required: true, unique: true },
	path: { type: String },
	name: { type: String },
	size: { type: Number },
	type: { type: String },
	flatFileName: { type: String },
	thumbnail: { type: String },
	permissions: [{
		userId: { type: Schema.Types.ObjectId, ref: 'user' },
		permissions: [{ type: String, enum: permissionTypes }],
	}],
	lockId: { type: Schema.Types.ObjectId },
	shareToken: { type: String },
	schoolId: { type: Schema.Types.ObjectId, ref: 'school' },
	studentCanEdit: { type: Boolean, default: false },
	createdAt: { type: Date, default: Date.now },
	updatedAt: { type: Date, default: Date.now },
});


const run = async () => {
	mongoose.connect(process.env.DB_URL || 'mongodb://localhost:27017/schulcloud', { user: process.env.DB_USERNAME, pass: process.env.DB_PASSWORD });

	const oldfileModel = mongoose.model('oldfile', oldFileSchema, '_files');

	const errorHandler = (err) => {
		console.log('Error', err);
		return undefined;
	};

	// take lessons
	let lessons = await lessonsModel.find({
		contents: {
			$not: { $size: 0 },
		},
	}, { contents: 1, _id: 1 }).exec().catch(errorHandler);

	lessons = lessons
		.filter(lesson => lesson.contents.some(c => c.component === 'text'));

	const promises = lessons.map((lesson) => {
		const regex = /(?:src|href)=\"(.*?\/files\/file\?(?:path|file)=.+?\/([0-9a-z]+?)\/.*?)\"/gm;
		const { contents } = lesson;

		const lessonPromises = contents
			.map((content) => {
				if (content.component !== 'text' || !regex.test(content.content.text)) {
					return Promise.resolve(false);
				}
				console.log(`Touching lesson with ID ${lesson._id}`);

				const oldIds = content.content.text
					.match(regex)
					.map(str => str.replace(regex, '$2'));

				console.log(`Found old ids ${oldIds}`);

				const oldPromises = oldIds
					.map(id => oldfileModel.findOne({ _id: id }).lean().exec().catch(errorHandler));

				return Promise.all(oldPromises)
					.then((oldFiles) => {
						const newFiles = oldFiles
							.filter(file => file)
							.map(file => convertDocument(file))
							.map(file => FileModel.findOne(file).exec().catch(errorHandler));

						return Promise.all(newFiles);
					})
					.then((files) => {
						const update = contents.map((c) => {
							if (c.component === 'text' && regex.test(c.content.text)) {
								const { text } = c.content;
								c.content.text = text.replace(regex, (...[match, attribute, id]) => {
									if (files[oldIds.indexOf(id)]) {
										return match.replace(attribute, `/files/file?file=${files[oldIds.indexOf(id)]._id}`);
									}
									return match;
								});
							}
							return c;
						});
						return lessonsModel
							.update({ _id: lesson._id }, { contents: update }).exec().catch(errorHandler);
					});
			});

		return Promise.all(lessonPromises);
	});

	return Promise.all(promises);
};

module.exports = {
	ran,
	name,
	run,
};

@@ -2604,14 +2604,14 @@
 le)=
+(
 .+?%5C/
-(
 %5B0-9
@@ -2620,15 +2620,15 @@
 z%5D+?
-)
 %5C/.*?)
+)
 %5C%22/g
@@ -2910,18 +2910,19 @@
 onst old
-Id
+Key
 s = cont
@@ -3033,19 +3033,26 @@
 old 
-id
+path key
 s $%7Bold
-Id
+Key
 s%7D%60)
@@ -3081,18 +3081,19 @@
 es = old
-Id
+Key
 s%0A%09%09%09%09%09.
@@ -3096,18 +3096,141 @@
 %09%09%09.map(
-id
+(key) =%3E %7B%0A%09%09%09%09%09%09const fn = key.split('/').pop();%0A%09%09%09%09%09%09return key.replace(fn, encodeURIComponent(fn));%0A%09%09%09%09%09%7D)%0A%09%09%09%09%09.map(key
  =%3E oldf
@@ -3252,15 +3252,11 @@
 e(%7B 
-_id: id
+key
  %7D).
@@ -3815,18 +3815,19 @@
 ribute, 
-id
+key
 %5D) =%3E %7B%0A
@@ -3839,36 +3839,70 @@
 %09%09%09%09
-if (files%5BoldIds.indexOf(id)
+const oldKey = oldKeys.indexOf(key);%0A%09%09%09%09%09%09%09%09%09if (files%5BoldKey
 %5D) %7B
@@ -3977,23 +3977,11 @@
 %5Bold
-Ids.indexOf(id)
+Key
 %5D._i

Fix key extraction for old files (#494)