const { setSurvey, transaction } = require('../connection');

async function patch (projectId, eventId, payload, opts = {}) {

	const p = payload; // Shorter
	const client = await setSurvey(projectId);
	try {
		await transaction.begin(client);

		// The order of attributes in an object is not defined, so
		// in theory we could get a different order if we made separate
		// calls to Object.keys() and Object.values(), unlikely as that
		// might be.
		let k = [];
		let v = [];
		Object.entries(p).forEach(i => { k.push(i[0]); v.push(i[1]); });

		const text = `
			UPDATE event_log
			SET
				${k.map((k, i) => `${k} = $${i+2}`).join(",\n")}
			WHERE id = $1;
		`;
		const values = [ eventId, ...v ];

		await client.query(text, values);

		// NOTE Horrible hack warning.
		// If we try to do the UPDATE on event_log, as you normally would,
		// we get a constraint violation on `event_log_full_validity_check`.
		// We would normally set that constraint as DEFERRABLE, except that
		// as of version 14, PostgreSQL does not support deferrable CHECK
		// constraints:
		// https://www.postgresql.org/docs/current/sql-createtable.html
		// So the options that I can think of are either not to use a transaction
		// or to apply this second update directly on the `event_log_full` table.

		const text1 = `
			UPDATE event_log_full
			SET remarks = replace_placeholders(remarks, tstamp, sequence, point)
			WHERE id = $1 AND validity @> current_timestamp;
		`;
		const values1 = [ eventId ];

		await client.query(text1, values1);

		await transaction.commit(client);
	} catch (err) {
		err.origin = __filename;
		throw err;
	} finally {
		client.release(); // implies ROLLBACK;
	}

	return;
}

module.exports = patch;
