const jwt = require('jsonwebtoken');
const config = require('../config/config');
const User = require('../models/User');
// JWT Authentication Middleware
const authenticateToken = async (req, res, next) => {
    try {
        const authHeader = req.headers.authorization;
        const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
        if (!token) {
            return res.status(401).json({
                status: 'error',
                message: 'Access token is required'
            });
        }
        // Verify token
        const decoded = jwt.verify(token, config.jwt.secret);
        // Find user to ensure they still exist and are active
        const user = await User.findById(decoded.id);
        if (!user || !user.is_active) {
            return res.status(401).json({
                status: 'error',
                message: 'Invalid or expired token'
            });
        }
        // Add user info to request
        req.user = {
            id: user.id,
            organization_id: user.organization_id,
            email: user.email,
            role: user.role,
            role_id: user.role_id,
            name: user.name
        };
        next();
    }
    catch (error) {
        if (error.name === 'JsonWebTokenError') {
            return res.status(401).json({
                status: 'error',
                message: 'Invalid token'
            });
        }
        else if (error.name === 'TokenExpiredError') {
            return res.status(401).json({
                status: 'error',
                message: 'Token has expired'
            });
        }
        next(error);
    }
};
// Role-based authorization middleware
const authorize = (...roles) => {
    return (req, res, next) => {
        if (!req.user) {
            return res.status(401).json({
                status: 'error',
                message: 'Authentication required'
            });
        }
        if (!roles.includes(req.user.role)) {
            return res.status(403).json({
                status: 'error',
                message: 'Insufficient permissions'
            });
        }
        next();
    };
};
// Helper function to check if user has specific permissions
const hasPermission = async (userId, requiredPermissions) => {
    try {
        const { pool } = require('../config/database');
        // Get user's role_id first
        const [userRows] = await pool.execute('SELECT role_id FROM users WHERE id = ? AND is_active = 1', [userId]);
        if (userRows.length === 0)
            return false;
        const roleId = userRows[0].role_id;
        // Get user's permissions from role
        const [permissions] = await pool.execute(`
      SELECT p.name as permission_name
      FROM role_permissions rp
      JOIN permissions p ON rp.permission_id = p.id
      WHERE rp.role_id = ?
    `, [roleId]);
        const userPermissions = permissions.map(p => p.permission_name);
        // Check if user has any of the required permissions
        return requiredPermissions.some(permission => userPermissions.includes(permission));
    }
    catch (error) {
        console.error('Error checking permissions:', error);
        return false;
    }
};
// Helper function to check if user has all required permissions
const hasAllPermissions = async (userId, requiredPermissions) => {
    try {
        const { pool } = require('../config/database');
        // Get user's role_id first
        const [userRows] = await pool.execute('SELECT role_id FROM users WHERE id = ? AND is_active = 1', [userId]);
        if (userRows.length === 0)
            return false;
        const roleId = userRows[0].role_id;
        // Get user's permissions from role
        const [permissions] = await pool.execute(`
      SELECT p.name as permission_name
      FROM role_permissions rp
      JOIN permissions p ON rp.permission_id = p.id
      WHERE rp.role_id = ?
    `, [roleId]);
        const userPermissions = permissions.map(p => p.permission_name);
        // Check if user has all required permissions
        return requiredPermissions.every(permission => userPermissions.includes(permission));
    }
    catch (error) {
        console.error('Error checking permissions:', error);
        return false;
    }
};
// Permission-based authorization middleware
const authorizePermission = (...permissions) => {
    return async (req, res, next) => {
        try {
            if (!req.user) {
                return res.status(401).json({
                    status: 'error',
                    message: 'Authentication required'
                });
            }
            // Super Admin has full access - bypass all permission checks
            if (req.user.role === 'Super Admin' || req.user.role_id === 1) {
                return next();
            }
            // Get user permissions from database dynamically
            const { pool } = require('../config/database');
            // Get the user's role permissions
            const [rolePermissions] = await pool.execute(`
        SELECT p.name as permission_name
        FROM role_permissions rp
        JOIN permissions p ON rp.permission_id = p.id
        WHERE rp.role_id = ?
      `, [req.user.role_id]);
            const userPermissions = rolePermissions.map(rp => rp.permission_name);
            // Check if user has any of the required permissions
            const hasPermission = permissions.some(permission => userPermissions.includes(permission));
            if (!hasPermission) {
                return res.status(403).json({
                    status: 'error',
                    message: 'Insufficient permissions'
                });
            }
            next();
        }
        catch (error) {
            return res.status(500).json({
                status: 'error',
                message: 'Internal server error'
            });
        }
    };
};
// Optional authentication middleware (doesn't fail if no token)
const optionalAuth = async (req, res, next) => {
    try {
        const authHeader = req.headers.authorization;
        const token = authHeader && authHeader.split(' ')[1];
        if (token) {
            const decoded = jwt.verify(token, config.jwt.secret);
            const user = await User.findById(decoded.id);
            if (user && user.is_active) {
                req.user = {
                    id: user.id,
                    email: user.email,
                    role: user.role,
                    role_id: user.role_id,
                    name: user.name
                };
            }
        }
        next();
    }
    catch (error) {
        // Continue without authentication if token is invalid
        next();
    }
};
module.exports = {
    authenticateToken,
    authorize,
    authorizePermission,
    optionalAuth,
    hasPermission,
    hasAllPermissions
};
//# sourceMappingURL=auth.js.map