'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';
