const bcryptjs = require('bcryptjs');

/**
 * @param {import('sequelize').Sequelize} sequelize The Sequelize instance
 * @param {import('sequelize').DataTypes} DataTypes Sequelize's data types
 * @returns {import('sequelize').ModelCtor<import('sequelize').Model>} The Users model
 */
module.exports = (sequelize, DataTypes) => {
  const Users = sequelize.define(
    'Users',
    {
      id: {
        type: DataTypes.UUID,
        defaultValue: DataTypes.UUIDV4,
        allowNull: false,
        primaryKey: true,
      },
      firstname: {
        type: DataTypes.STRING,
        allowNull: true,
      },
      middlename: {
        type: DataTypes.STRING,
        allowNull: true,
      },
      lastname: {
        type: DataTypes.STRING,
        allowNull: true,
      },
      fullname: {
        type: DataTypes.STRING,
        allowNull: true,
      },
      phone_no: {
        type: DataTypes.STRING,
        allowNull: true,
      },
      email_address: {
        type: DataTypes.STRING,
        allowNull: true,
      },
      password: {
        type: DataTypes.STRING,
        allowNull: true,
      },
      birthdate: {
        type: DataTypes.DATEONLY,
        allowNull: true,
      },
      image: {
        type: DataTypes.STRING,
        allowNull: true,
        defaultValue: null,
      },
      is_phone_verified: {
        type: DataTypes.BOOLEAN,
        allowNull: false,
        defaultValue: false,
      },
      is_email_verified: {
        type: DataTypes.BOOLEAN,
        allowNull: true,
        defaultValue: false,
      },
      is_host: {
        type: DataTypes.BOOLEAN,
        allowNull: false,
        defaultValue: false,
      },
      hosting_date: {
        type: DataTypes.DATEONLY,
        allowNull: true,
      },
      has_pending_host_application: {
        type: DataTypes.BOOLEAN,
        allowNull: false,
        defaultValue: false,
      },
      status: {
        type: DataTypes.BOOLEAN,
        allowNull: false,
        defaultValue: true,
      },
      address_long: {
        type: DataTypes.DOUBLE,
        allowNull: true,
      },
      address_lat: {
        type: DataTypes.DOUBLE,
        allowNull: true,
      },
      address_country: {
        type: DataTypes.STRING,
        allowNull: true,
      },
      address_street: {
        type: DataTypes.STRING,
        allowNull: true,
      },
      address_apt: {
        type: DataTypes.STRING,
        allowNull: true,
      },
      address_city: {
        type: DataTypes.STRING,
        allowNull: true,
      },
      address_state: {
        type: DataTypes.STRING,
        allowNull: true,
      },
      address_zip: {
        type: DataTypes.STRING,
        allowNull: true,
      },
      valid_id_image: {
        type: DataTypes.STRING,
        allowNull: true,
      },
      language: {
        type: DataTypes.STRING,
        defaultValue: 'English',
      },
      about_me: {
        type: DataTypes.TEXT,
        allowNull: true,
      },
      school: {
        type: DataTypes.STRING,
        allowNull: true,
      },
      work: {
        type: DataTypes.STRING,
        allowNull: true,
      },
      music: {
        type: DataTypes.STRING,
        allowNull: true,
      },
      lived_in: {
        type: DataTypes.STRING,
        allowNull: true,
      },
      languages: {
        type: DataTypes.JSON,
        allowNull: true,
      },
      pets: {
        type: DataTypes.STRING,
        allowNull: true,
      },
      hangouts: {
        type: DataTypes.STRING,
        allowNull: true,
      },
      birth_year: {
        type: DataTypes.STRING,
        allowNull: true,
      },
      likes: {
        type: DataTypes.STRING,
        allowNull: true,
      },
      dislikes: {
        type: DataTypes.STRING,
        allowNull: true,
      },
      interests: {
        type: DataTypes.JSON,
        allowNull: true,
      },
      show_travels: {
        type: DataTypes.BOOLEAN,
        defaultValue: true,
      },
      verified: {
        type: DataTypes.BOOLEAN,
        defaultValue: false,
      },
      is_facebook: {
        type: DataTypes.BOOLEAN,
        defaultValue: false,
      },
      is_google: {
        type: DataTypes.BOOLEAN,
        defaultValue: false,
      },
      is_apple: {
        type: DataTypes.BOOLEAN,
        defaultValue: false,
      },
      google_id: {
        type: DataTypes.STRING,
        allowNull: true,
      },
      facebook_id: {
        type: DataTypes.TEXT,
        allowNull: true,
      },
      apple_id: {
        type: DataTypes.TEXT,
        allowNull: true,
      },
      phone_no_2: {
        type: DataTypes.STRING,
        allowNull: true,
      },
      email_2: {
        type: DataTypes.STRING,
        allowNull: true,
      },
      nickname: {
        type: DataTypes.STRING,
        allowNull: true,
      },
      custom_url: {
        type: DataTypes.STRING,
        allowNull: true,
      },
      preferred_currency: {
        type: DataTypes.STRING,
        allowNull: false,
        defaultValue: 'Philippine Peso',
      },
    },
    {
      hooks: {
        beforeCreate: async (customer) => {
          if (customer.changed('password')) {
            const saltRounds = 10;
            customer.password = await bcryptjs.hash(customer.password, saltRounds);
          }
        },
        beforeUpdate: async (customer) => {
          if (customer.changed('password')) {
            const saltRounds = 10;
            customer.password = await bcryptjs.hash(customer.password, saltRounds);
          }
        },
      },
      tableName: 'users',
      timestamps: true,
    },
  );

  Users.associate = function (models) {
    Users.hasMany(models.HostReviews, {
      foreignKey: 'host_id',
      as: 'hostReviews',
    });

    Users.hasMany(models.Bookings, {
      foreignKey: 'customer_id',
    });

    Users.hasMany(models.CustomerReviews, {
      as: 'customerReviews',
      foreignKey: 'user_id',
    });

    Users.hasMany(models.HostManagers, {
      foreignKey: 'email',
      sourceKey: 'email_address',
      as: 'hostManagers',
    });

    Users.hasMany(models.Listings, {
      foreignKey: 'host_id',
      as: 'listings',
    });
  };

  Users.prototype.validatePassword = async function (plainPassword) {
    // If user has no password (social login), return false
    if (!this.password) {
      return false;
    }
    return bcryptjs.compare(plainPassword, this.password);
  };

  return Users;
};
