'use strict';

/** @type {import('sequelize-cli').Migration} */
module.exports = {
	async up(queryInterface, Sequelize) {
		return queryInterface.sequelize.transaction(async (transaction) => {
			await queryInterface.changeColumn(
				'conversation_members',
				'user_id',
				{
					type: Sequelize.UUID,
					allowNull: true,
				},
				{ transaction },
			);
			await queryInterface.bulkUpdate(
				'conversation_members',
				{ user_id: null },
				{
					user_id: {
						[Sequelize.Op.notIn]: Sequelize.literal('(SELECT id FROM users)'),
					},
				},
			);
			await queryInterface.addConstraint('conversation_members', {
				type: 'foreign key',
				fields: ['user_id'],
				references: { table: 'users', field: 'id' },
				onDelete: 'SET NULL',
				name: 'conversation_members_user_id_foreign_key',
				transaction,
			});
			await queryInterface.addConstraint('conversation_members', {
				type: 'foreign key',
				fields: ['convo_id'],
				references: { table: 'conversations', field: 'id' },
				onDelete: 'CASCADE',
				name: 'conversation_members_convo_id_foreign_key',
				transaction,
			});

			await queryInterface.changeColumn(
				'messages',
				'convo_id',
				{
					type: Sequelize.UUID,
					allowNull: true,
				},
				{ transaction },
			);
			await queryInterface.changeColumn(
				'messages',
				'sender_id',
				{
					type: Sequelize.UUID,
					allowNull: true,
				},
				{ transaction },
			);
			await queryInterface.bulkUpdate(
				'messages',
				{ sender_id: null },
				{
					sender_id: {
						[Sequelize.Op.notIn]: Sequelize.literal('(SELECT id FROM users)'),
					},
				},
				{ transaction },
			);

			await queryInterface.bulkDelete(
				'messages',
				{
					convo_id: {
						[Sequelize.Op.notIn]: Sequelize.literal('(SELECT id FROM conversations)'),
					},
				},
				{ transaction },
			);
			await queryInterface.addConstraint('messages', {
				type: 'foreign key',
				fields: ['convo_id'],
				references: { table: 'conversations', field: 'id' },
				onDelete: 'CASCADE',
				name: 'messages_convo_id_foreign_key',
				transaction,
			});
			await queryInterface.addConstraint('messages', {
				type: 'foreign key',
				fields: ['sender_id'],
				references: { table: 'users', field: 'id' },
				onDelete: 'SET NULL',
				name: 'messages_sender_id_foreign_key',
				transaction,
			});
			await queryInterface.addConstraint('message_attachments', {
				type: 'foreign key',
				fields: ['message_id'],
				references: { table: 'messages', field: 'id' },
				onDelete: 'CASCADE',
				name: 'message_attachments_message_id_foreign_key',
				transaction,
			});
		});
	},

	async down(queryInterface, Sequelize) {
		return queryInterface.sequelize.transaction(async (transaction) => {
			await queryInterface.removeConstraint('conversation_members', 'conversation_members_user_id_foreign_key', {
				transaction,
			});
			await queryInterface.removeConstraint('conversation_members', 'conversation_members_convo_id_foreign_key', {
				transaction,
			});
			await queryInterface.changeColumn(
				'conversation_members',
				'user_id',
				{
					type: Sequelize.INTEGER,
					allowNull: false,
				},
				{ transaction },
			);

			await queryInterface.removeConstraint('messages', 'messages_convo_id_foreign_key', {
				transaction,
			});
			await queryInterface.removeConstraint('messages', 'messages_sender_id_foreign_key', {
				transaction,
			});
			await queryInterface.removeConstraint('message_attachments', 'message_attachments_message_id_foreign_key', {
				transaction,
			});
			await queryInterface.bulkUpdate('messages', { sender_id: TEST_UUID }, { sender_id: null }, { transaction });
			await queryInterface.changeColumn(
				'messages',
				'convo_id',
				{
					type: Sequelize.INTEGER,
					allowNull: false,
				},
				{ transaction },
			);
			await queryInterface.changeColumn(
				'messages',
				'sender_id',
				{
					type: Sequelize.INTEGER,
					allowNull: false,
				},
				{ transaction },
			);
		});
	},
};

const TEST_UUID = '00000000-0000-0000-0000-000000000000';
