
import { Request, Response } from 'express';
import { User } from '../models/User';
import bcrypt from 'bcrypt';
import mongoose from 'mongoose';
import { isCsmEnabled } from '../csm/config';
import { getCsmMembers } from '../csm/directory';
import { mapCsmMemberToAomUser } from '../csm/mapUser';

/** When CSM manages identity, user CRUD/password ops are disabled here. */
const CSM_MANAGED_MESSAGE = 'Quản lý người dùng đã chuyển sang CSM. Vui lòng thao tác trên csm.vuphong.vn.';
function rejectIfCsmManaged(res: Response): boolean {
    if (isCsmEnabled()) {
        res.status(409).json({ success: false, message: CSM_MANAGED_MESSAGE });
        return true;
    }
    return false;
}

function parseIdsParam(raw: unknown): string[] | undefined {
    if (typeof raw !== 'string' || !raw.trim()) return undefined;
    return raw.split(',').map((s) => s.trim()).filter(Boolean);
}

/** Danh sách rút gọn cho gán việc / dropdown — mọi user đã đăng nhập. */
export const getUserDirectory = async (req: Request, res: Response) => {
    try {
        if (isCsmEnabled()) {
            const ids = parseIdsParam(req.query.ids);
            // List = only users granted AOM access (with their AOM role); ids = resolve any user.
            const members = await getCsmMembers({ status: 'Active', ids, granted: !ids });
            res.json({ success: true, data: members.map(mapCsmMemberToAomUser) });
            return;
        }
        const users = await User.find({ status: 'Active' })
            .select('_id name email role status department companyId')
            .lean();
        const data = users.map((user) => ({
            ...user,
            active: user.status === 'Active',
        }));
        res.json({ success: true, data });
    } catch (error: any) {
        res.status(isCsmEnabled() ? 502 : 500).json({ success: false, message: error.message });
    }
};

export const getUsers = async (req: Request, res: Response) => {
    try {
        if (isCsmEnabled()) {
            const status = typeof req.query.status === 'string' ? req.query.status : 'Active';
            const ids = parseIdsParam(req.query.ids);
            const members = await getCsmMembers({ status, ids, granted: !ids });
            res.json({ success: true, data: members.map(mapCsmMemberToAomUser) });
            return;
        }
        const users = await User.find({}).select('-password'); // Exclude password
        // Map status to active for frontend compatibility
        const usersWithActive = users.map(user => {
            const userObj = user.toObject() as unknown as Record<string, unknown>;
            userObj.active = user.status === 'Active';
            return userObj;
        });
        res.json({ success: true, data: usersWithActive });
    } catch (error: any) {
        res.status(isCsmEnabled() ? 502 : 500).json({ success: false, message: error.message });
    }
};

export const createUser = async (req: Request, res: Response) => {
    if (rejectIfCsmManaged(res)) return;
    try {
        const { email, password, name, role, status, companyId, department, scope } = req.body;

        // Normalize email to match the schema (lowercase + trim) so the duplicate
        // check is consistent with what actually gets stored / indexed as unique.
        const normalizedEmail = typeof email === 'string' ? email.trim().toLowerCase() : email;

        const existingUser = await User.findOne({ email: normalizedEmail });
        if (existingUser) {
            return res.status(400).json({ success: false, message: 'Email already exists' });
        }

        // Xử lý scope: đảm bảo luôn có giá trị hợp lệ
        let finalScope = ['Tất cả']; // Mặc định
        if (scope) {
            if (Array.isArray(scope) && scope.length > 0) {
                finalScope = scope;
            } else if (typeof scope === 'string' && scope.trim() !== '') {
                finalScope = [scope];
            }
        }

        const newUser = new User({
            email: normalizedEmail,
            password,
            name,
            role,
            status: status || 'Active',
            companyId,
            department,
            scope: finalScope
        });

        await newUser.save();

        // Map status to active for frontend compatibility
        const userResponse = newUser.toObject() as unknown as Record<string, unknown>;
        userResponse.active = newUser.status === 'Active';

        res.status(201).json({ success: true, message: 'User created successfully', data: userResponse });
    } catch (error: any) {
        res.status(500).json({ success: false, message: error.message });
    }
};

export const updateUser = async (req: Request, res: Response) => {
    if (rejectIfCsmManaged(res)) return;
    try {
        const { id } = req.params;
        const updateData = { ...req.body };

        // Remove _id from update data as it is immutable in MongoDB
        delete updateData._id;

        // Prevent password update via this endpoint
        delete updateData.password;

        // Support both string and ObjectId for lookup
        const query = {
            $or: [
                { _id: id },
                { _id: mongoose.Types.ObjectId.isValid(id) ? new mongoose.Types.ObjectId(id) : null }
            ].filter(f => f._id !== null)
        };

        const user = await User.findOneAndUpdate(
            query,
            updateData,
            { new: true, runValidators: true }
        ).select('-password');

        if (!user) {
            return res.status(404).json({ success: false, message: 'User not found' });
        }

        // Map status to active for frontend compatibility
        const userResponse = user.toObject() as unknown as Record<string, unknown>;
        userResponse.active = user.status === 'Active';

        res.json({ success: true, message: 'User updated successfully', data: userResponse });
    } catch (error: any) {
        res.status(500).json({ success: false, message: error.message });
    }
};

export const deleteUser = async (req: Request, res: Response) => {
    if (rejectIfCsmManaged(res)) return;
    try {
        const { id } = req.params;

        // Support both string and ObjectId for lookup
        const query = {
            $or: [
                { _id: id },
                { _id: mongoose.Types.ObjectId.isValid(id) ? new mongoose.Types.ObjectId(id) : null }
            ].filter(f => f._id !== null)
        };

        const user = await User.findOneAndDelete(query);

        if (!user) {
            return res.status(404).json({ success: false, message: 'User not found' });
        }

        res.json({ success: true, message: 'User deleted successfully' });
    } catch (error: any) {
        res.status(500).json({ success: false, message: error.message });
    }
};

export const resetPassword = async (req: Request, res: Response) => {
    if (rejectIfCsmManaged(res)) return;
    try {
        const { id } = req.params;
        const { newPassword } = req.body;

        if (!newPassword) {
            return res.status(400).json({ success: false, message: 'Unknown error' });
        }

        const user = await User.findById(id);
        if (!user) {
            return res.status(404).json({ success: false, message: 'User not found' });
        }

        user.password = newPassword;
        await user.save(); // Triggers pre-save hash

        res.json({ success: true, message: 'Password reset successfully' });
    } catch (error: any) {
        res.status(500).json({ success: false, message: error.message });
    }
};

export const changePassword = async (req: Request, res: Response) => {
    if (rejectIfCsmManaged(res)) return;
    try {
        const { id } = req.params;
        const { currentPassword, newPassword } = req.body;

        const user = await User.findById(id).select('+password');
        if (!user) {
            return res.status(404).json({ success: false, message: 'User not found' });
        }

        const isMatch = await user.comparePassword(currentPassword);
        if (!isMatch) {
            return res.status(400).json({ success: false, message: 'Incorrect current password' });
        }

        user.password = newPassword;
        await user.save();

        res.json({ success: true, message: 'Password changed successfully' });
    } catch (error: any) {
        res.status(500).json({ success: false, message: error.message });
    }
};
