import { getPrismaClient } from '../db/prisma.js';
import { createLogger } from '@4runr/shared';
const logger = createLogger('Gateway:RBAC');
export async function checkPermission(userId, resource, action) {
    try {
        const prisma = await getPrismaClient();
        const user = await prisma.user.findUnique({
            where: { id: userId },
            include: {
                roles: {
                    include: {
                        role: {
                            include: {
                                permissions: {
                                    include: {
                                        permission: true
                                    }
                                }
                            }
                        }
                    }
                }
            }
        });
        if (!user || user.status !== 'ACTIVE') {
            return false;
        }
        for (const userRole of user.roles) {
            for (const rolePermission of userRole.role.permissions) {
                const perm = rolePermission.permission;
                if (perm.resource === resource && perm.action === action) {
                    return true;
                }
                if (perm.resource === '*' || perm.action === '*') {
                    return true;
                }
                if (perm.resource === resource && perm.action === '*') {
                    return true;
                }
                if (perm.resource === '*' && perm.action === action) {
                    return true;
                }
            }
        }
        return false;
    }
    catch (error) {
        logger.error('Error checking permission', {
            userId,
            resource,
            action,
            error: error instanceof Error ? error.message : String(error)
        });
        return false;
    }
}
export async function getRBACContext(userId) {
    try {
        const prisma = await getPrismaClient();
        const user = await prisma.user.findUnique({
            where: { id: userId },
            include: {
                roles: {
                    include: {
                        role: {
                            include: {
                                permissions: {
                                    include: {
                                        permission: true
                                    }
                                }
                            }
                        }
                    }
                }
            }
        });
        if (!user || user.status !== 'ACTIVE') {
            return null;
        }
        const roles = [];
        const permissions = new Set();
        for (const userRole of user.roles) {
            roles.push(userRole.role.name);
            for (const rolePermission of userRole.role.permissions) {
                const perm = rolePermission.permission;
                permissions.add(`${perm.resource}:${perm.action}`);
            }
        }
        return {
            userId: user.id,
            roles,
            permissions: Array.from(permissions)
        };
    }
    catch (error) {
        logger.error('Error getting RBAC context', {
            userId,
            error: error instanceof Error ? error.message : String(error)
        });
        return null;
    }
}
export function requirePermission(resource, action) {
    return async (request, reply) => {
        const auth = request.auth || request.user;
        if (!auth || !auth.sub) {
            reply.status(401).send({
                error: 'unauthorized',
                message: 'Authentication required'
            });
            return;
        }
        const userId = auth.sub;
        const hasPermission = await checkPermission(userId, resource, action);
        if (!hasPermission) {
            logger.warn('Permission denied', {
                userId,
                resource,
                action,
                path: request.url
            });
            reply.status(403).send({
                error: 'forbidden',
                message: `Permission denied: ${resource}:${action}`,
                required: `${resource}:${action}`
            });
            return;
        }
        const rbacContext = await getRBACContext(userId);
        if (rbacContext) {
            request.rbac = rbacContext;
        }
    };
}
export function requireAnyPermission(permissions) {
    return async (request, reply) => {
        const auth = request.auth || request.user;
        if (!auth || !auth.sub) {
            reply.status(401).send({
                error: 'unauthorized',
                message: 'Authentication required'
            });
            return;
        }
        const userId = auth.sub;
        for (const perm of permissions) {
            const hasPermission = await checkPermission(userId, perm.resource, perm.action);
            if (hasPermission) {
                const rbacContext = await getRBACContext(userId);
                if (rbacContext) {
                    request.rbac = rbacContext;
                }
                return;
            }
        }
        logger.warn('Permission denied (requireAny)', {
            userId,
            required: permissions.map(p => `${p.resource}:${p.action}`),
            path: request.url
        });
        reply.status(403).send({
            error: 'forbidden',
            message: 'Permission denied',
            required: permissions.map(p => `${p.resource}:${p.action}`)
        });
    };
}
export function requireAllPermissions(permissions) {
    return async (request, reply) => {
        const auth = request.auth || request.user;
        if (!auth || !auth.sub) {
            reply.status(401).send({
                error: 'unauthorized',
                message: 'Authentication required'
            });
            return;
        }
        const userId = auth.sub;
        for (const perm of permissions) {
            const hasPermission = await checkPermission(userId, perm.resource, perm.action);
            if (!hasPermission) {
                logger.warn('Permission denied (requireAll)', {
                    userId,
                    missing: `${perm.resource}:${perm.action}`,
                    path: request.url
                });
                reply.status(403).send({
                    error: 'forbidden',
                    message: `Permission denied: ${perm.resource}:${perm.action}`,
                    required: permissions.map(p => `${p.resource}:${p.action}`)
                });
                return;
            }
        }
        const rbacContext = await getRBACContext(userId);
        if (rbacContext) {
            request.rbac = rbacContext;
        }
    };
}
export async function hasRole(userId, roleName) {
    try {
        const prisma = await getPrismaClient();
        const user = await prisma.user.findUnique({
            where: { id: userId },
            include: {
                roles: {
                    include: {
                        role: true
                    }
                }
            }
        });
        if (!user || user.status !== 'ACTIVE') {
            return false;
        }
        return user.roles.some(ur => ur.role.name === roleName);
    }
    catch (error) {
        logger.error('Error checking role', {
            userId,
            roleName,
            error: error instanceof Error ? error.message : String(error)
        });
        return false;
    }
}
//# sourceMappingURL=rbac.js.map