'use strict';

/** @type {import('sequelize-cli').Migration} */
module.exports = {
	async up(queryInterface, Sequelize) {
		return queryInterface.sequelize.transaction(async (transaction) => {
			await queryInterface.changeColumn(
				'bookings',
				'customer_id',
				{
					type: Sequelize.UUID,
					allowNull: true,
				},
				{ transaction },
			);
			await queryInterface.changeColumn(
				'bookings',
				'host_id',
				{
					type: Sequelize.UUID,
					allowNull: true,
				},
				{ transaction },
			);
			await queryInterface.changeColumn(
				'bookings',
				'listing_id',
				{
					type: Sequelize.UUID,
					allowNull: true,
				},
				{ transaction },
			);
			await queryInterface.bulkUpdate(
				'bookings',
				{ listing_id: null },
				{
					listing_id: {
						[Sequelize.Op.notIn]: Sequelize.literal('(SELECT id FROM listings)'),
					},
				},
				{ transaction },
			);
			await queryInterface.bulkUpdate(
				'bookings',
				{ host_id: null },
				{
					host_id: {
						[Sequelize.Op.notIn]: Sequelize.literal('(SELECT id FROM users)'),
					},
				},
				{ transaction },
			);
			await queryInterface.bulkUpdate(
				'bookings',
				{ customer_id: null },
				{
					customer_id: {
						[Sequelize.Op.notIn]: Sequelize.literal('(SELECT id FROM users)'),
					},
				},
				{ transaction },
			);
			await queryInterface.addConstraint('bookings', {
				type: 'foreign key',
				fields: ['customer_id'],
				references: { table: 'users', field: 'id' },
				onDelete: 'SET NULL',
				name: 'bookings_customer_id_foreign_key',
				transaction,
			});
			await queryInterface.addConstraint('bookings', {
				type: 'foreign key',
				fields: ['host_id'],
				references: { table: 'users', field: 'id' },
				onDelete: 'SET NULL',
				name: 'bookings_host_id_foreign_key',
				transaction,
			});
			await queryInterface.addConstraint('bookings', {
				type: 'foreign key',
				fields: ['listing_id'],
				references: { table: 'listings', field: 'id' },
				onDelete: 'SET NULL',
				name: 'bookings_listing_id_foreign_key',
				transaction,
			});

			await queryInterface.bulkDelete('booking_add_ons', {
				booking_id: {
					[Sequelize.Op.notIn]: Sequelize.literal('(SELECT id FROM bookings)'),
				},
			});
			await queryInterface.addConstraint('booking_add_ons', {
				type: 'foreign key',
				fields: ['booking_id'],
				references: { table: 'bookings', field: 'id' },
				onDelete: 'CASCADE',
				name: 'booking_add_ons_booking_id_foreign_key',
				transaction,
			});
		});
	},

	async down(queryInterface, Sequelize) {
		return queryInterface.sequelize.transaction(async (transaction) => {
			await queryInterface.removeConstraint('bookings', 'bookings_customer_id_foreign_key', { transaction });
			await queryInterface.removeConstraint('bookings', 'bookings_host_id_foreign_key', { transaction });
			await queryInterface.removeConstraint('bookings', 'bookings_listing_id_foreign_key', { transaction });
			await queryInterface.removeConstraint('booking_add_ons', 'booking_add_ons_booking_id_foreign_key', {
				transaction,
			});

			await queryInterface.bulkUpdate('bookings', { customer_id: TEST_UUID }, { customer_id: null });
			await queryInterface.bulkUpdate('bookings', { host_id: TEST_UUID }, { host_id: null });
			await queryInterface.bulkUpdate('bookings', { listing_id: TEST_UUID }, { listing_id: null });

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

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