module.exports = {
  async up(queryInterface, Sequelize) {
    const transaction = await queryInterface.sequelize.transaction();

    try {
      const tableRows = await queryInterface.sequelize.query(
        "SELECT to_regclass('public.page_elements') AS regclass_name;",
        {
          transaction,
          type: Sequelize.QueryTypes.SELECT,
        },
      );

      if (!tableRows[0]?.regclass_name) {
        await transaction.commit();
        return;
      }

      const nullableRows = await queryInterface.sequelize.query(
        `SELECT is_nullable
         FROM information_schema.columns
         WHERE table_schema = 'public'
           AND table_name = 'page_elements'
           AND column_name = 'pageId';`,
        {
          transaction,
          type: Sequelize.QueryTypes.SELECT,
        },
      );

      if (!nullableRows.length || nullableRows[0].is_nullable === 'YES') {
        await transaction.commit();
        return;
      }

      await queryInterface.changeColumn(
        'page_elements',
        'pageId',
        {
          type: Sequelize.DataTypes.UUID,
          allowNull: true,
          references: {
            model: 'tour_pages',
            key: 'id',
          },
        },
        { transaction },
      );

      await transaction.commit();
    } catch (err) {
      await transaction.rollback();
      throw err;
    }
  },

  async down(queryInterface, Sequelize) {
    const transaction = await queryInterface.sequelize.transaction();

    try {
      const tableRows = await queryInterface.sequelize.query(
        "SELECT to_regclass('public.page_elements') AS regclass_name;",
        {
          transaction,
          type: Sequelize.QueryTypes.SELECT,
        },
      );

      if (!tableRows[0]?.regclass_name) {
        await transaction.commit();
        return;
      }

      const nullableRows = await queryInterface.sequelize.query(
        `SELECT is_nullable
         FROM information_schema.columns
         WHERE table_schema = 'public'
           AND table_name = 'page_elements'
           AND column_name = 'pageId';`,
        {
          transaction,
          type: Sequelize.QueryTypes.SELECT,
        },
      );

      if (!nullableRows.length || nullableRows[0].is_nullable === 'NO') {
        await transaction.commit();
        return;
      }

      const nullCountRows = await queryInterface.sequelize.query(
        'SELECT COUNT(*)::int AS count FROM "page_elements" WHERE "pageId" IS NULL;',
        {
          transaction,
          type: Sequelize.QueryTypes.SELECT,
        },
      );

      if (Number(nullCountRows[0]?.count || 0) > 0) {
        throw new Error('Cannot make page_elements.pageId NOT NULL because NULL values exist.');
      }

      await queryInterface.changeColumn(
        'page_elements',
        'pageId',
        {
          type: Sequelize.DataTypes.UUID,
          allowNull: false,
          references: {
            model: 'tour_pages',
            key: 'id',
          },
        },
        { transaction },
      );

      await transaction.commit();
    } catch (err) {
      await transaction.rollback();
      throw err;
    }
  },
};
