const Role = require('../models/roleSchema');
const Resource = require('../models/resourceSchema');
const mongoose = require('mongoose');
const AuditLog = require('../models/auditLogSchema');

const createRole = async (req, res) => {
    try {
        const { name, displayName, description, permissions, isActive } = req.body;
        let roleName = name.toUpperCase();

        // Check if role name already exists
        const existingRole = await Role.findOne({ name: roleName });
        if (existingRole) {
            return res.status(409).json({
                error: 'Role with this name already exists',
                code: 'DUPLICATE_ROLE_NAME'
            });
        }
        if (permissions) {
            for (const permission of permissions) {
                if (!permission.resource || !mongoose.Types.ObjectId.isValid(permission.resource)) {
                    return res.status(400).json({
                        error: 'Invalid resource ID in permissions',
                        code: 'INVALID_RESOURCE_ID'
                    });
                }

                const resourceExists = await Resource.findById(permission.resource);
                if (!resourceExists) {
                    return res.status(400).json({
                        error: `Resource ${permission.resource} not found`,
                        code: 'RESOURCE_NOT_FOUND'
                    });
                }

                // Validate actions
                const validActions = ['view', 'add', 'edit', 'delete', 'update'];
                const invalidActions = permission.actions.filter(action => !validActions.includes(action));
                if (invalidActions.length > 0) {
                    return res.status(400).json({
                        error: `Invalid actions: ${invalidActions.join(', ')}`,
                        code: 'INVALID_ACTIONS'
                    });
                }
            }
        }
        // Validate permissions resources exist


        // Create role
        const role = new Role({
            name: roleName.trim(),
            description: description?.trim(),
            permissions,
            displayName,
            isActive: isActive !== undefined ? isActive : true,
            createdBy: req?.user?.userId
        });

        await role.save();

        // Populate the created role
        const populatedRole = await Role.findById(role._id)
            .populate('permissions.resource', 'name displayName')
            .populate('createdBy', 'name email');

        // Log the action
        await AuditLog.create({
            userId: req.user._id,
            action: 'role_created',
            ipAddress: req.ip,
        });

        res.status(201).json({
            message: 'Role created successfully',
            role: populatedRole
        });
    } catch (error) {
        console.error('Create role error:', error);
        res.status(500).json({
            error: 'Internal server error',
            code: 'CREATE_ROLE_FAILED'
        });
    }
}

const getAllRoles = async (req, res) => {
    try {
        const {
            isActive,
            page = 1,
            limit = 10,
            sortBy = 'createdAt',
            sortOrder = 'desc'
        } = req.query;

        // Build filter
        let filter = {};
        if (isActive !== undefined) {
            filter.isActive = isActive === 'true';
        }

        //Not include own role and super admin role 
        if (req.user && req.user.userId) {
            console.log(true);
            // filter.createdBy = req.user.userId;
            // filter._id = { $ne: req.user.userId };
            filter.name = { $nin: ['super_admin', req.user.role.name] };
        }

        // Build sort
        const sort = {};
        sort[sortBy] = sortOrder === 'desc' ? -1 : 1;

        // Execute query
        const roles = await Role.find(filter)
            .populate('permissions.resource', 'name')
            .populate('createdBy', 'name email')
            .sort(sort)
            .limit(limit * 1)
            .skip((page - 1) * limit);

        const total = await Role.countDocuments(filter);

        res.status(200).json({
            roles,
            pagination: {
                currentPage: parseInt(page),
                totalPages: Math.ceil(total / limit),
                totalRecords: total,
                limit: parseInt(limit)
            }
        });
    } catch (error) {
        console.error('Get roles error:', error);
        res.status(500).json({
            error: 'Internal server error',
            code: 'GET_ROLES_FAILED'
        });
    }
}

const getRoleById = async (req, res) => {
    try {
        const { id } = req.params;

        if (!mongoose.Types.ObjectId.isValid(id)) {
            return res.status(400).json({
                error: 'Invalid role ID format',
                code: 'INVALID_ROLE_ID'
            });
        }

        const role = await Role.findById(id)
            .populate('permissions.resource', 'name description')
            .populate('createdBy', 'name email');

        if (!role) {
            return res.status(404).json({
                error: 'Role not found',
                code: 'ROLE_NOT_FOUND'
            });
        }

        return res.status(200).json({
            role,
            message: 'Role retrieved successfully'
        });
    } catch (error) {
        console.error('Get role by ID error:', error);
        res.status(500).json({
            error: 'Internal server error',
            code: 'GET_ROLE_FAILED'
        });
    }
}

const updateRole = async (req, res) => {
    try {
        const { id } = req.params;
        const { name, description, permissions, isActive } = req.body;
        let roleName = name?.toUpperCase();
        if (!mongoose.Types.ObjectId.isValid(id)) {
            return res.status(400).json({
                error: 'Invalid role ID format',
                code: 'INVALID_ROLE_ID'
            });
        }

        const role = await Role.findById(id);
        if (!role) {
            return res.status(404).json({
                error: 'Role not found',
                code: 'ROLE_NOT_FOUND'
            });
        }

        // Check if name is being changed and if new name exists
        if (roleName && roleName !== role.name) {
            const existingRole = await Role.findOne({
                name: roleName,
                _id: { $ne: id }
            });
            if (existingRole) {
                return res.status(409).json({
                    error: 'Role with this name already exists',
                    code: 'DUPLICATE_ROLE_NAME'
                });
            }
        }

        // Validate permissions if provided
        if (permissions) {
            for (const permission of permissions) {
                if (!permission.resource || !mongoose.Types.ObjectId.isValid(permission.resource)) {
                    return res.status(400).json({
                        error: 'Invalid resource ID in permissions',
                        code: 'INVALID_RESOURCE_ID'
                    });
                }

                const resourceExists = await Resource.findById(permission.resource);
                if (!resourceExists) {
                    return res.status(400).json({
                        error: `Resource ${permission.resource} not found`,
                        code: 'RESOURCE_NOT_FOUND'
                    });
                }
            }
        }

        // Store original values for audit
        // const originalValues = {
        //     name: role.name,
        //     displayName: role.displayName,   
        //     description: role.description,
        //     permissions: role.permissions,
        //     isActive: role.isActive
        // };

        // Update fields
        if (name !== undefined) role.name = roleName.trim();
        if (description !== undefined) role.description = description?.trim();
        if (permissions !== undefined) role.permissions = permissions;
        if (isActive !== undefined) role.isActive = isActive;

        await role.save();

        // Get updated role with populated fields
        const updatedRole = await Role.findById(id)
            .populate('permissions.resource', 'name')
            .populate('createdBy', 'name email');

        // Log the action
        await AuditLog.create({
            userId: req.user._id,
            action: 'role_updated',
            ipAddress: req.ip,
        });

        return res.status(200).json({
            message: 'Role updated successfully',
            role: updatedRole
        });
    } catch (error) {
        console.error('Update role error:', error);
        res.status(500).json({
            error: 'Internal server error',
            code: 'UPDATE_ROLE_FAILED'
        });
    }
}

const deleteRole = async (req, res) => {
    try {
        const { id } = req.params;

        if (!mongoose.Types.ObjectId.isValid(id)) {
            return res.status(400).json({
                error: 'Invalid role ID format',
                code: 'INVALID_ROLE_ID'
            });
        }

        const role = await Role.findById(id);
        if (!role) {
            return res.status(404).json({
                error: 'Role not found',
                code: 'ROLE_NOT_FOUND'
            });
        }

        // Soft delete
        role.isActive = false;
        await role.save();

        // Log the action
        await AuditLog.create({
            userId: req.user._id,
            action: 'role_deleted',
            ipAddress: req.ip,
        });

        return res.status(200).json({
            message: 'Role deactivated successfully',
            role
        });
    } catch (error) {
        console.error('Delete role error:', error);
        res.status(500).json({
            error: 'Internal server error',
            code: 'DELETE_ROLE_FAILED'
        });
    }
}

const getAllResources = async (req, res) => {
    try {
        // const {
        //     isActive,
        //     page = 1,
        //     limit = 10,
        //     sortBy = 'createdAt',
        //     sortOrder = 'desc',
        //     search
        // } = req.query;

        // // Build filter
        // let filter = {};

        // if (isActive !== undefined) {
        //     filter.isActive = isActive === 'true';
        // }

        // if (search) {
        //     filter.$or = [
        //         { name: { $regex: search, $options: 'i' } },
        //         { displayName: { $regex: search, $options: 'i' } },
        //         { description: { $regex: search, $options: 'i' } }
        //     ];
        // }

        // // Build sort
        // const sort = {};
        // sort[sortBy] = sortOrder === 'desc' ? -1 : 1;

        // Execute query
        const resources = await Resource.find({
            isActive: true,
            name: { $nin: "tenant" } // Never show tenant resource
        }).select('name displayName description')
            .sort({ displayName: 1 });
        // .sort(sort)
        // .limit(limit * 1)
        // .skip((page - 1) * limit);

        // const total = await Resource.countDocuments(filter);

        res.status(200).json({
            resources,
            // pagination: {
            //     currentPage: parseInt(page),
            //     totalPages: Math.ceil(total / limit),
            //     totalRecords: total,
            //     limit: parseInt(limit)
            // }
        });
    } catch (error) {
        console.error('Get resources error:', error);
        res.status(500).json({
            error: 'Internal server error',
            code: 'GET_RESOURCES_FAILED'
        });
    }
}


module.exports = {
    createRole,
    getAllRoles,
    getRoleById,
    updateRole,
    deleteRole,
    getAllResources
};