// models/userModel.js
const { DataTypes } = require('sequelize');
const bcrypt = require('bcryptjs');
const sequelize = require('../config/sequelize');
const { ROLES } = require("../utils/global")

// Define User model
const UserModel = sequelize.define('User', {
    id: {
        type: DataTypes.INTEGER,
        primaryKey: true,
        autoIncrement: true
    },
    username: {
        type: DataTypes.STRING,
        allowNull: false,
        unique: true
    },
    email: {
        type: DataTypes.STRING,
        allowNull: false,
        unique: true,
        validate: {
            isEmail: true
        }
    },
    password: {
        type: DataTypes.STRING,
        allowNull: false
    },
    role: {
        type: DataTypes.STRING,
        allowNull: false,
        defaultValue: 'user'
    },
    status: {
        type: DataTypes.INTEGER,
        allowNull: false,
        defaultValue: 0
    },
}, {
    timestamps: true,
    createdAt: 'created_at',
    updatedAt: 'updated_at',
    tableName: 'users'
});

// Hash password before saving
UserModel.beforeCreate(async (user) => {
    const saltRounds = 10;
    user.password = await bcrypt.hash(user.password, saltRounds);
});

// Hash password before updating if changed
UserModel.beforeUpdate(async (user) => {
    if (user.changed('password')) {
        const saltRounds = 10;
        user.password = await bcrypt.hash(user.password, saltRounds);
    }
});

class User {
    // Create a new user
    static async create(userData) {
        try {
            const user = await UserModel.create(userData);

            return {
                id: user.id,
                username: user.username,
                email: user.email,
                role: user.role,
            };
        } catch (error) {
            throw error;
        }
    }

    // Find a user by their email
    static async findByEmail(email) {
        try {
            return await UserModel.findOne({ where: { email } });
        } catch (error) {
            throw error;
        }
    }

    // Find a user by their username
    static async findByUsername(username) {
        try {
            return await UserModel.findOne({ where: { username } });
        } catch (error) {
            throw error;
        }
    }

    static async findBycontact_number(contact_number) {
        try {
            return await UserModel.findOne({ where: { contact_number } });
        } catch (error) {
            throw error;
        }
    }

    // Find a user by their ID
    static async findById(id) {
        try {
            const user = await UserModel.findByPk(id, {
                attributes: ['id', 'username', 'email', 'role','created_at', 'updated_at']
            });
            return user;
        } catch (error) {
            throw error;
        }
    }

    // Update a user's information
    static async updateUser(id, updateData, role) {
        try {
            if (role === ROLES["ADMIN"]) {
                await UserModel.update(updateData, {
                    where: { id },
                    individualHooks: true // To trigger beforeUpdate hooks
                });

                return this.findById(id);
            }

            return false

        } catch (error) {
            throw error;
        }
    }



    // Get single User
    static async Get_Single_User(id) {
        try {
            let user = await UserModel.findByPk(id);
            if (!user) {
                throw new Error('User not found');
            }
    
            user = JSON.parse(JSON.stringify(user, null, 2));
    
            const {
                id: userId,
                username,
                email,
                role,
                status,
                created_at,
                updated_at
            } = user;
    
            return {
                id: userId,
                username,
                email,
                role,
                status,
                created_at,
                updated_at
            };
        } catch (error) {
            throw error;
        }
    }
    
    // Delete a user
    static async deleteUser(id, role) {
        try {
            const user = await UserModel.findByPk(id);
            if (!user) {
                throw new Error('User not found');
            }


            if (role === ROLES["ADMIN"]) {
                await user.destroy();
                return { success: true, message: 'User deleted successfully' };
            }
            return false
        } catch (error) {
            throw error;
        }
    }

    static async getUsers(role) {
        try {

            if (role === ROLES["ADMIN"]) {
                let users = await UserModel.findAll();
                users = JSON.parse(JSON.stringify(users, null, 2))
                users = users.map(({
                    id,
                    username,
                    email,
                    role,
                    status,
                    created_at,
                    updated_at
                }) => {
                    return {
                        id,
                        username,
                        email,
                        role, 
                        status,
                        created_at,
                        updated_at
                    }
                })
                if (!users.length) {
                    throw new Error('User not found');
                }

                return users
            }
            return false
        } catch (error) {
            throw error;
        }
    }

    // Verify a user's password
    static async verifyPassword(plainPassword, hashedPassword) {
        return await bcrypt.compare(plainPassword, hashedPassword);
    }
}

module.exports = { User, UserModel };