'use strict';

/** @type {import('sequelize-cli').Migration} */
module.exports = {
	async up(queryInterface, Sequelize) {
		return queryInterface.sequelize.transaction(async (transaction) => {
			await queryInterface.changeColumn(
				'customer_reviews',
				'user_id',
				{
					allowNull: true,
					type: Sequelize.UUID,
				},
				{ transaction },
			);

			await queryInterface.changeColumn(
				'customer_reviews',
				'host_id',
				{
					allowNull: true,
					type: Sequelize.UUID,
				},
				{
					transaction,
				},
			);

			await queryInterface.changeColumn(
				'host_reviews',
				'user_id',
				{
					allowNull: true,
					type: Sequelize.UUID,
				},
				{
					transaction,
				},
			);

			await queryInterface.changeColumn(
				'host_reviews',
				'host_id',
				{
					allowNull: true,
					type: Sequelize.UUID,
				},
				{
					transaction,
				},
			);

			await queryInterface.changeColumn(
				'listing_reviews',
				'user_id',
				{
					allowNull: true,
					type: Sequelize.UUID,
				},
				{
					transaction,
				},
			);

			await queryInterface.changeColumn(
				'listing_reviews',
				'listing_id',
				{
					allowNull: true,
					type: Sequelize.UUID,
				},
				{
					transaction,
				},
			);

			await queryInterface.bulkUpdate(
				'customer_reviews',
				{ user_id: null },
				{
					user_id: {
						[Sequelize.Op.notIn]: Sequelize.literal('(SELECT id FROM users)'),
					},
				},
			);

			await queryInterface.bulkUpdate(
				'customer_reviews',
				{ host_id: null },
				{
					host_id: {
						[Sequelize.Op.notIn]: Sequelize.literal('(SELECT id FROM users)'),
					},
				},
			);

			await queryInterface.bulkUpdate(
				'host_reviews',
				{ user_id: null },
				{
					user_id: {
						[Sequelize.Op.notIn]: Sequelize.literal('(SELECT id FROM users)'),
					},
				},
			);

			await queryInterface.bulkUpdate(
				'host_reviews',
				{ host_id: null },
				{
					host_id: {
						[Sequelize.Op.notIn]: Sequelize.literal('(SELECT id FROM users)'),
					},
				},
			);

			await queryInterface.bulkUpdate(
				'listing_reviews',
				{ user_id: null },
				{
					user_id: {
						[Sequelize.Op.notIn]: Sequelize.literal('(SELECT id FROM users)'),
					},
				},
			);

			await queryInterface.bulkUpdate(
				'listing_reviews',
				{ listing_id: null },
				{
					listing_id: {
						[Sequelize.Op.notIn]: Sequelize.literal('(SELECT id FROM listings)'),
					},
				},
			);

			await queryInterface.addConstraint('customer_reviews', {
				fields: ['user_id'],
				type: 'foreign key',
				name: 'fk_customer_reviews_user_id',
				references: {
					table: 'users',
					field: 'id',
				},
				onDelete: 'SET NULL',
				transaction,
			});

			await queryInterface.addConstraint('customer_reviews', {
				fields: ['host_id'],
				type: 'foreign key',
				name: 'fk_customer_reviews_host_id',
				references: {
					table: 'users',
					field: 'id',
				},
				onDelete: 'SET NULL',
				transaction,
			});

			await queryInterface.addConstraint('host_reviews', {
				fields: ['user_id'],
				type: 'foreign key',
				name: 'fk_host_reviews_user_id',
				references: {
					table: 'users',
					field: 'id',
				},
				onDelete: 'SET NULL',
				transaction,
			});

			await queryInterface.addConstraint('host_reviews', {
				fields: ['host_id'],
				type: 'foreign key',
				name: 'fk_host_reviews_host_id',
				references: {
					table: 'users',
					field: 'id',
				},
				onDelete: 'SET NULL',
				transaction,
			});

			await queryInterface.addConstraint('listing_reviews', {
				fields: ['user_id'],
				type: 'foreign key',
				name: 'fk_listing_reviews_user_id',
				references: {
					table: 'users',
					field: 'id',
				},
				onDelete: 'SET NULL',
				transaction,
			});

			await queryInterface.addConstraint('listing_reviews', {
				fields: ['listing_id'],
				type: 'foreign key',
				name: 'fk_listing_reviews_listing_id',
				references: {
					table: 'listings',
					field: 'id',
				},
				onDelete: 'CASCADE',
				transaction,
			});
		});
	},

	async down(queryInterface, Sequelize) {
		return queryInterface.sequelize.transaction(async (transaction) => {
			await queryInterface.removeConstraint('customer_reviews', 'fk_customer_reviews_user_id', { transaction });
			await queryInterface.removeConstraint('customer_reviews', 'fk_customer_reviews_host_id', { transaction });
			await queryInterface.removeConstraint('host_reviews', 'fk_host_reviews_user_id', { transaction });
			await queryInterface.removeConstraint('host_reviews', 'fk_host_reviews_host_id', { transaction });
			await queryInterface.removeConstraint('listing_reviews', 'fk_listing_reviews_user_id', { transaction });
			await queryInterface.removeConstraint('listing_reviews', 'fk_listing_reviews_listing_id', { transaction });

			await queryInterface.bulkUpdate('customer_reviews', { user_id: TEST_UUID }, { user_id: null });
			await queryInterface.bulkUpdate('customer_reviews', { host_id: TEST_UUID }, { host_id: null });
			await queryInterface.bulkUpdate('host_reviews', { user_id: TEST_UUID }, { user_id: null });
			await queryInterface.bulkUpdate('host_reviews', { host_id: TEST_UUID }, { host_id: null });
			await queryInterface.bulkUpdate('listing_reviews', { user_id: TEST_UUID }, { user_id: null });
			await queryInterface.bulkUpdate('listing_reviews', { listing_id: TEST_UUID }, { listing_id: null });

			await queryInterface.changeColumn(
				'customer_reviews',
				'user_id',
				{
					allowNull: false,
					type: Sequelize.UUID,
				},
				{ transaction },
			);

			await queryInterface.changeColumn(
				'customer_reviews',
				'host_id',
				{
					allowNull: false,
					type: Sequelize.UUID,
				},
				{ transaction },
			);

			await queryInterface.changeColumn(
				'host_reviews',
				'user_id',
				{
					allowNull: false,
					type: Sequelize.UUID,
				},
				{ transaction },
			);

			await queryInterface.changeColumn(
				'host_reviews',
				'host_id',
				{
					allowNull: false,
					type: Sequelize.UUID,
				},
				{ transaction },
			);

			await queryInterface.changeColumn(
				'listing_reviews',
				'user_id',
				{
					allowNull: false,
					type: Sequelize.UUID,
				},
				{ transaction },
			);

			await queryInterface.changeColumn(
				'listing_reviews',
				'listing_id',
				{
					allowNull: false,
					type: Sequelize.UUID,
				},
				{ transaction },
			);
		});
	},
};

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