/**
 * 用户模型
 * @file User.js
 * @description 银行系统用户模型定义
 */
const { DataTypes } = require('sequelize');
const bcrypt = require('bcryptjs');
const BaseModel = require('./BaseModel');
const { sequelize } = require('../config/database');

class User extends BaseModel {
  /**
   * 验证密码
   * @param {String} password 待验证的密码
   * @returns {Promise<Boolean>} 验证结果
   */
  async validPassword(password) {
    try {
      if (!password || !this.password) {
        return false;
      }
      const bcrypt = require('bcryptjs');
      return await bcrypt.compare(password, this.password);
    } catch (error) {
      console.error('密码验证错误:', error);
      return false;
    }
  }

  /**
   * 获取用户角色
   * @returns {Promise<Array>} 用户角色列表
   */
  async getRoles() {
    try {
      const { Role } = require('./index');
      const role = await Role.findByPk(this.role_id);
      return role ? [role] : [];
    } catch (error) {
      console.error('获取用户角色失败:', error);
      return [];
    }
  }

  /**
   * 检查用户是否具有指定角色
   * @param {String|Array} roleName 角色名称或角色名称数组
   * @returns {Promise<Boolean>} 检查结果
   */
  async hasRole(roleName) {
    const roles = await this.getRoles();
    const roleNames = roles.map(role => role.name);
    
    if (Array.isArray(roleName)) {
      return roleName.some(name => roleNames.includes(name));
    }
    
    return roleNames.includes(roleName);
  }

  /**
   * 获取用户账户列表
   * @returns {Promise<Array>} 账户列表
   */
  async getAccounts() {
    try {
      const { Account } = require('./index');
      return await Account.findAll({
        where: { user_id: this.id, status: 'active' }
      });
    } catch (error) {
      console.error('获取用户账户失败:', error);
      return [];
    }
  }

  /**
   * 获取用户安全信息（不包含密码）
   * @returns {Object} 用户安全信息
   */
  getSafeInfo() {
    return super.getSafeInfo(['password', 'pin']);
  }
}

// 初始化User模型
User.init({
  id: {
    type: DataTypes.INTEGER,
    primaryKey: true,
    autoIncrement: true
  },
  username: {
    type: DataTypes.STRING(50),
    allowNull: false,
    unique: true,
    validate: {
      len: [3, 50]
    }
  },
  email: {
    type: DataTypes.STRING(100),
    allowNull: false,
    unique: true,
    validate: {
      isEmail: true
    }
  },
  password: {
    type: DataTypes.STRING(255),
    allowNull: false,
    validate: {
      len: [6, 255]
    }
  },
  phone: {
    type: DataTypes.STRING(20),
    allowNull: true,
    validate: {
      is: /^1[3-9]\d{9}$/
    }
  },
  real_name: {
    type: DataTypes.STRING(50),
    allowNull: false
  },
  id_card: {
    type: DataTypes.STRING(18),
    allowNull: false,
    unique: true,
    validate: {
      is: /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/
    }
  },
  avatar: {
    type: DataTypes.STRING(255),
    allowNull: true
  },
  role_id: {
    type: DataTypes.INTEGER,
    allowNull: false,
    defaultValue: 2, // 默认为普通用户角色ID
    references: {
      model: 'bank_roles',
      key: 'id'
    }
  },
  status: {
    type: DataTypes.ENUM('active', 'inactive', 'suspended', 'locked'),
    defaultValue: 'active'
  },
  last_login: {
    type: DataTypes.DATE,
    allowNull: true
  },
  login_attempts: {
    type: DataTypes.INTEGER,
    defaultValue: 0
  },
  locked_until: {
    type: DataTypes.DATE,
    allowNull: true
  },
  created_at: {
    type: DataTypes.DATE,
    allowNull: false,
    defaultValue: DataTypes.NOW
  },
  updated_at: {
    type: DataTypes.DATE,
    allowNull: false,
    defaultValue: DataTypes.NOW
  }
}, {
  sequelize,
  tableName: 'bank_users',
  modelName: 'User',
  timestamps: true,
  underscored: true,
  createdAt: 'created_at',
  updatedAt: 'updated_at',
  hooks: {
    beforeCreate: async (user) => {
      if (user.password && !user.password.startsWith('$2a$')) {
        user.password = await bcrypt.hash(user.password, 10);
      }
    },
    beforeUpdate: async (user) => {
      if (user.changed('password') && user.password && !user.password.startsWith('$2a$')) {
        user.password = await bcrypt.hash(user.password, 10);
      }
    }
  }
});

module.exports = User;