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

async function saveSequenceQCs (projectId, results) {

	const client = await setSurvey(projectId);
	await transaction.begin(client);

	async function deleteQCSequence (sequence, qc_id) {
		console.log("deleteQCSequence", sequence, qc_id);
		const text = `
			UPDATE raw_lines
			SET
				meta = meta #- ARRAY[ 'qc', $2 ]
			WHERE
				sequence = $1;
		`;

		const values = [ sequence, qc_id ];

		return await client.query(text, values);
	}

	async function deleteQCEvent (sequence, qc_id) {
		console.log("deleteQCEvent", sequence, qc_id);
		// NOTE that we delete from event_log_full
		// because the event is readonly and we can't otherwise
		// modify it via event_log (though it'd be nice to)
		const text = `
			DELETE
			FROM event_log_full
			WHERE
				sequence = $1
				AND meta->>'qc_id' = $2;
		`;

		return await client.query(text, [ sequence, qc_id ]);
	}

	async function updateQCSequence (sequence, qc_id, remarks, labels) {
		console.log("updateQCSequence", sequence, qc_id, remarks);
		const text = `
			UPDATE raw_lines
			SET
				meta = jsonb_set(meta, '{qc}',
					coalesce(meta->'qc', '{}'::jsonb) ||  jsonb_build_object($2::text, $3::text)
				)
			WHERE
				sequence = $1
		`;

		// NOTE We ignore labels for now.
		// The idea is that one day we will associate labels with
		// sequences just like we associate labels with shotpoints
		// in the event log.
		const values = [ sequence, qc_id, remarks, /*labels*/ ];

		return await client.query(text, values);
	}

	async function updateQCEvent (sequence, shot, qc_id, remarks, labels) {
		console.log("updateQCEvent", sequence, shot, qc_id, remarks);
		const text = `
			INSERT INTO event_log (sequence, point, remarks, labels, meta)
			SELECT $1, $2, $4, $5, $6
			WHERE NOT EXISTS (
				SELECT 1 FROM event_log WHERE sequence = $1 AND point = $2 AND meta->>'qc_id' = $3
			);
		`;

		const values = [ sequence, shot, qc_id, remarks, labels, {qc_id, readonly: true} ];

		return await client.query(text, values);
	};


	for (const sequence in results) {
		for (const qc_id in results[sequence]) {
			const result = results[sequence][qc_id];

			await deleteQCSequence(sequence, qc_id);

			// For shot QCs we get a pass/fail for every shot, but
			// for sequence QCs we may only get individual shot results
			// for failed shots. So what we do is remove all data related
			// to this QC id from the event log, then we (re-)insert data
			// for failed shots. Not ideal.
			await deleteQCEvent(sequence, qc_id);

			if (result !== true) {

				const remarks = typeof result === "string"
					? result
					: result?.remarks;
				const labels = result?.labels ?? [];
				await updateQCSequence(sequence, qc_id, remarks, labels);

				if (result?.shots) {
					for (const shot in result.shots) {
						const shotResult = result.shots[shot];
						// `true` means QC passed. Otherwise expect string or object.
						if (shotResult !== true) {
							// Add or replace an existing event for this QC
							const remarks = typeof shotResult === "string"
								? shotResult
								: shotResult?.remarks;
							const labels = shotResult?.labels ?? [];
							await updateQCEvent(sequence, shot, qc_id, remarks, labels);
						}
					}
				}
			}
		}
		console.log("Done sequence", sequence);
	}

	await transaction.commit(client);
	await client.release();

}

module.exports = saveSequenceQCs;
