const bcrypt = require('bcryptjs');
const { User, Role } = require('../models/foundation');
const { logAction } = require('../utils/logger');
const { generateSecurePassword } = require('../utils/passwordGenerator');
const { sendPasswordResetEmail, sendWelcomeEmail } = require('../services/notificationService');

exports.getAllUsers = async () => {
    return await User.findAll({
        include: [{ model: Role }],
        attributes: { exclude: ['password'] }
    });
};

exports.createUser = async (data, creatorId) => {
    const { fullName, email, phone, password, roleId, clientId } = data;

    // hash password
    const salt = await bcrypt.genSalt(10);
    const hashedPassword = await bcrypt.hash(password, salt);

    const user = await User.create({
        fullName,
        email,
        phone,
        password: hashedPassword,
        roleId,
        clientId,
        isActive: true,
        mustChangePassword: true,
        credentialsSent: false
    });

    // Send Welcome Email (Safely)
    try {
        await sendWelcomeEmail(user, password);
        user.credentialsSent = true;
        await user.save();
    } catch (err) {
        console.error('Failed to send welcome email during user creation:', err);
    }

    await logAction(creatorId, 'CREATE', 'USER', { id: user.id, email: user.email }, null);
    return user;
};

exports.updateUser = async (id, data, modifierId) => {
    const user = await User.findByPk(id);
    if (!user) throw new Error('User not found');

    if (data.password) {
        const salt = await bcrypt.genSalt(10);
        data.password = await bcrypt.hash(data.password, salt);
    }

    await user.update(data);
    await logAction(modifierId, 'UPDATE', 'USER', { id: user.id }, null);
    return user;
};

exports.toggleStatus = async (id, modifierId) => {
    const user = await User.findByPk(id);
    if (!user) throw new Error('User not found');

    user.isActive = !user.isActive;
    await user.save();

    await logAction(modifierId, 'TOGGLE_STATUS', 'USER', { id: user.id, status: user.isActive }, null);
    return user;
};

exports.getRoles = async () => {
    return await Role.findAll();
};

exports.deleteUser = async (id, modifierId) => {
    const user = await User.findByPk(id);
    if (!user) throw new Error('User not found');

    await user.destroy();
    await logAction(modifierId, 'DELETE', 'USER', { id }, null);
    return true;
};

exports.resetUserPassword = async (id, modifierId) => {
    const user = await User.findByPk(id);
    if (!user) throw new Error('User not found');

    const plainPassword = generateSecurePassword();
    const salt = await bcrypt.genSalt(10);
    const hashedPassword = await bcrypt.hash(plainPassword, salt);

    user.password = hashedPassword;
    user.mustChangePassword = true;
    await user.save();

    await sendPasswordResetEmail(user, plainPassword);
    await logAction(modifierId, 'RESET_PASSWORD', 'USER', { id: user.id }, null);

    return plainPassword;
};

exports.resendUserCredentials = async (id, modifierId) => {
    const user = await User.findByPk(id);
    if (!user) throw new Error('User not found');

    const plainPassword = generateSecurePassword();
    const salt = await bcrypt.genSalt(10);
    const hashedPassword = await bcrypt.hash(plainPassword, salt);

    // Update password and flag
    user.password = hashedPassword;
    user.mustChangePassword = true;
    user.credentialsSent = false; // Reset to false until email sent successfully
    await user.save();

    // Send Welcome Email (which contains portal URL, username, and password)
    let emailSent = false;
    try {
        await sendWelcomeEmail(user, plainPassword);
        user.credentialsSent = true;
        await user.save();
        emailSent = true;
    } catch (err) {
        console.error('Failed to resend credentials:', err);
        throw new Error('User updated but email failed to send.');
    }

    await logAction(modifierId, 'RESEND_CREDENTIALS', 'USER', { id: user.id }, null);
    return { success: emailSent, newPassword: plainPassword };
};
