const { DataTypes, Model } = require('sequelize');
const sequelize = require('../config/database');
const bcrypt = require('bcryptjs');
const logger = require('../config/logger');

class User extends Model {
  async comparePassword(candidatePassword) {
    try {
      return await bcrypt.compare(candidatePassword, this.password);
    } catch (error) {
      logger.error('Password comparison error:', error);
      throw new Error('Password comparison failed');
    }
  }
}

User.init({
  id: {
    type: DataTypes.UUID,
    defaultValue: DataTypes.UUIDV4,
    primaryKey: true
  },
  email: {
    type: DataTypes.STRING,
    unique: true,
    allowNull: false,
    validate: {
      isEmail: true,
      len: [5, 255],
      notNull: { msg: 'Email is required' }
    }
  },
  password: {
    type: DataTypes.STRING,
    allowNull: false,
    validate: {
      len: [8, 255],
      notNull: { msg: 'Password is required' }
    }
  },
  name: {
    type: DataTypes.STRING,
    allowNull: false,
    validate: {
      len: [2, 100],
      notNull: { msg: 'Name is required' }
    }
  },
  role: {
    type: DataTypes.ENUM('user', 'admin'),
    defaultValue: 'user',
    validate: {
      isIn: [['user', 'admin']]
    }
  },
  lastLogin: {
    type: DataTypes.DATE
  },
  isActive: {
    type: DataTypes.BOOLEAN,
    defaultValue: true
  },
  passwordResetToken: DataTypes.STRING,
  passwordResetExpires: DataTypes.DATE,
  failedLoginAttempts: {
    type: DataTypes.INTEGER,
    defaultValue: 0
  },
  lockUntil: DataTypes.DATE
}, {
  sequelize,
  modelName: 'User',
  timestamps: true,
  paranoid: true,
  indexes: [
    { unique: true, fields: ['email'] },
    { fields: ['role'] },
    { fields: ['isActive'] }
  ]
});

User.beforeCreate(async (user) => {
  try {
    const salt = await bcrypt.genSalt(12);
    user.password = await bcrypt.hash(user.password, salt);
  } catch (error) {
    logger.error('Password hashing error:', error);
    throw new Error('Password hashing failed');
  }
});

User.beforeUpdate(async (user) => {
  if (user.changed('password')) {
    try {
      const salt = await bcrypt.genSalt(12);
      user.password = await bcrypt.hash(user.password, salt);
    } catch (error) {
      logger.error('Password update error:', error);
      throw new Error('Password update failed');
    }
  }
});

module.exports = User;