"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.optionalAuth = exports.requireTaskModify = exports.requireTaskAccess = exports.requireAllPermissions = exports.requireAnyPermission = exports.requirePermission = exports.authenticateToken = void 0;
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
const rbac_service_1 = require("../services/rbac.service");
/**
 * Extract and verify JWT token
 */
const authenticateToken = async (req, res, next) => {
    try {
        // Get token from Authorization header
        const authHeader = req.headers['authorization'];
        const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
        if (!token) {
            res.status(401).json({
                success: false,
                error: 'Access token required'
            });
            return;
        }
        // Verify token
        const secret = process.env.JWT_SECRET || 'default-secret-change-in-production';
        const payload = jsonwebtoken_1.default.verify(token, secret);
        // Get user context from RBAC service
        const userContext = await rbac_service_1.rbacService.getUserContext(payload.id);
        // Attach user context to request
        req.user = userContext;
        req.userId = payload.id;
        next();
    }
    catch (error) {
        if (error.name === 'TokenExpiredError') {
            res.status(401).json({
                success: false,
                error: 'Token expired'
            });
            return;
        }
        if (error.name === 'JsonWebTokenError') {
            res.status(401).json({
                success: false,
                error: 'Invalid token'
            });
            return;
        }
        res.status(500).json({
            success: false,
            error: 'Authentication failed'
        });
    }
};
exports.authenticateToken = authenticateToken;
/**
 * Require specific permission
 */
const requirePermission = (permission) => {
    return async (req, res, next) => {
        try {
            // Ensure user is authenticated
            if (!req.user || !req.userId) {
                res.status(401).json({
                    success: false,
                    error: 'Authentication required'
                });
                return;
            }
            // Check if user has the required permission
            const hasPermission = await rbac_service_1.rbacService.hasPermission(req.userId, permission);
            if (!hasPermission) {
                res.status(403).json({
                    success: false,
                    error: `Permission denied: ${permission} required`
                });
                return;
            }
            next();
        }
        catch (error) {
            res.status(500).json({
                success: false,
                error: 'Permission check failed'
            });
        }
    };
};
exports.requirePermission = requirePermission;
/**
 * Require any of the specified permissions
 */
const requireAnyPermission = (permissions) => {
    return async (req, res, next) => {
        try {
            // Ensure user is authenticated
            if (!req.user || !req.userId) {
                res.status(401).json({
                    success: false,
                    error: 'Authentication required'
                });
                return;
            }
            // Check if user has any of the required permissions
            const hasPermission = await rbac_service_1.rbacService.hasAnyPermission(req.userId, permissions);
            if (!hasPermission) {
                res.status(403).json({
                    success: false,
                    error: `Permission denied: One of [${permissions.join(', ')}] required`
                });
                return;
            }
            next();
        }
        catch (error) {
            res.status(500).json({
                success: false,
                error: 'Permission check failed'
            });
        }
    };
};
exports.requireAnyPermission = requireAnyPermission;
/**
 * Require all of the specified permissions
 */
const requireAllPermissions = (permissions) => {
    return async (req, res, next) => {
        try {
            // Ensure user is authenticated
            if (!req.user || !req.userId) {
                res.status(401).json({
                    success: false,
                    error: 'Authentication required'
                });
                return;
            }
            // Check if user has all of the required permissions
            const hasPermission = await rbac_service_1.rbacService.hasAllPermissions(req.userId, permissions);
            if (!hasPermission) {
                res.status(403).json({
                    success: false,
                    error: `Permission denied: All of [${permissions.join(', ')}] required`
                });
                return;
            }
            next();
        }
        catch (error) {
            res.status(500).json({
                success: false,
                error: 'Permission check failed'
            });
        }
    };
};
exports.requireAllPermissions = requireAllPermissions;
/**
 * Check task access permission
 */
const requireTaskAccess = async (req, res, next) => {
    try {
        // Ensure user is authenticated
        if (!req.user || !req.userId) {
            res.status(401).json({
                success: false,
                error: 'Authentication required'
            });
            return;
        }
        // Get task ID from params or body
        const taskId = req.params.id || req.params.taskId || req.body.taskId;
        if (!taskId) {
            res.status(400).json({
                success: false,
                error: 'Task ID required'
            });
            return;
        }
        // Check if user can access the task
        const canAccess = await rbac_service_1.rbacService.canAccessTask(req.userId, taskId);
        if (!canAccess) {
            res.status(403).json({
                success: false,
                error: 'Access denied to this task'
            });
            return;
        }
        next();
    }
    catch (error) {
        res.status(500).json({
            success: false,
            error: 'Task access check failed'
        });
    }
};
exports.requireTaskAccess = requireTaskAccess;
/**
 * Check task modification permission
 */
const requireTaskModify = async (req, res, next) => {
    try {
        // Ensure user is authenticated
        if (!req.user || !req.userId) {
            res.status(401).json({
                success: false,
                error: 'Authentication required'
            });
            return;
        }
        // Get task ID from params or body
        const taskId = req.params.id || req.params.taskId || req.body.taskId;
        if (!taskId) {
            res.status(400).json({
                success: false,
                error: 'Task ID required'
            });
            return;
        }
        // Check if user can modify the task
        const canModify = await rbac_service_1.rbacService.canModifyTask(req.userId, taskId);
        if (!canModify) {
            res.status(403).json({
                success: false,
                error: 'Permission denied to modify this task'
            });
            return;
        }
        next();
    }
    catch (error) {
        res.status(500).json({
            success: false,
            error: 'Task modification check failed'
        });
    }
};
exports.requireTaskModify = requireTaskModify;
/**
 * Optional authentication - doesn't fail if no token
 */
const optionalAuth = async (req, res, next) => {
    try {
        // Get token from Authorization header
        const authHeader = req.headers['authorization'];
        const token = authHeader && authHeader.split(' ')[1];
        if (!token) {
            // No token provided, continue without user context
            next();
            return;
        }
        // Verify token
        const secret = process.env.JWT_SECRET || 'default-secret-change-in-production';
        const payload = jsonwebtoken_1.default.verify(token, secret);
        // Get user context from RBAC service
        const userContext = await rbac_service_1.rbacService.getUserContext(payload.id);
        // Attach user context to request
        req.user = userContext;
        req.userId = payload.id;
        next();
    }
    catch (error) {
        // Token verification failed, continue without user context
        next();
    }
};
exports.optionalAuth = optionalAuth;
//# sourceMappingURL=rbac.middleware.js.map