'use strict';

const isMissingTableError = (err) => {
  const message = String(err && err.message);
  return message.includes('No description found')
    || message.includes('does not exist')
    || message.includes('Cannot read properties of undefined');
};

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

    try {
      try {
        await queryInterface.describeTable('place_offerings');
        await transaction.commit();
        return;
      } catch (err) {
        if (!isMissingTableError(err)) {
          throw err;
        }
      }

      await queryInterface.createTable('place_offerings', {
        id: {
          type: Sequelize.DataTypes.UUID,
          defaultValue: Sequelize.DataTypes.UUIDV4,
          primaryKey: true,
        },
        placeId: {
          type: Sequelize.DataTypes.UUID,
          allowNull: false,
          references: {
            key: 'id',
            model: 'places',
          },
        },
        name: {
          type: Sequelize.DataTypes.TEXT,
          allowNull: false,
        },
        description: {
          type: Sequelize.DataTypes.TEXT,
        },
        offering_type: {
          type: Sequelize.DataTypes.ENUM('product', 'service'),
          allowNull: false,
          defaultValue: 'product',
        },
        price: {
          type: Sequelize.DataTypes.DECIMAL,
        },
        stock_status: {
          type: Sequelize.DataTypes.ENUM('in_stock', 'limited', 'out_of_stock', 'by_request'),
          allowNull: false,
          defaultValue: 'by_request',
        },
        stock_quantity: {
          type: Sequelize.DataTypes.INTEGER,
        },
        is_verified: {
          type: Sequelize.DataTypes.BOOLEAN,
          allowNull: false,
          defaultValue: false,
        },
        is_active: {
          type: Sequelize.DataTypes.BOOLEAN,
          allowNull: false,
          defaultValue: true,
        },
        last_stock_update: {
          type: Sequelize.DataTypes.DATE,
        },
        createdAt: {
          type: Sequelize.DataTypes.DATE,
        },
        updatedAt: {
          type: Sequelize.DataTypes.DATE,
        },
        deletedAt: {
          type: Sequelize.DataTypes.DATE,
        },
        importHash: {
          type: Sequelize.DataTypes.STRING(255),
          allowNull: true,
          unique: true,
        },
      }, { transaction });

      await queryInterface.addIndex('place_offerings', ['placeId'], {
        transaction,
      });
      await queryInterface.addIndex('place_offerings', ['offering_type', 'stock_status'], {
        transaction,
      });
      await queryInterface.addIndex('place_offerings', ['is_active'], {
        transaction,
      });

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

  down: async (queryInterface) => {
    const transaction = await queryInterface.sequelize.transaction();

    try {
      let tableExists = true;
      try {
        await queryInterface.describeTable('place_offerings');
      } catch (err) {
        if (!isMissingTableError(err)) {
          throw err;
        }
        tableExists = false;
      }

      if (tableExists) {
        await queryInterface.dropTable('place_offerings', { transaction });
      }
      await queryInterface.sequelize.query('DROP TYPE IF EXISTS "enum_place_offerings_offering_type";', { transaction });
      await queryInterface.sequelize.query('DROP TYPE IF EXISTS "enum_place_offerings_stock_status";', { transaction });
      await transaction.commit();
    } catch (err) {
      await transaction.rollback();
      throw err;
    }
  },
};
