const logger = require('../config/logger');

/**
 * Role-Based Access Control (RBAC) Middleware
 * Restricts access based on admin roles
 */

/**
 * Role hierarchy (higher roles include permissions of lower roles)
 * super_admin > admin > operator
 */
const ROLE_HIERARCHY = {
  super_admin: 3,
  admin: 2,
  operator: 1,
};

/**
 * Resource permissions by role
 * Defines which roles can perform which actions on which resources
 */
const RESOURCE_PERMISSIONS = {
  users: {
    read: ['operator', 'admin', 'super_admin'],
    create: ['admin', 'super_admin'],
    update: ['admin', 'super_admin'],
    delete: ['super_admin'],
  },
  appointments: {
    read: ['operator', 'admin', 'super_admin'],
    create: ['operator', 'admin', 'super_admin'],
    update: ['operator', 'admin', 'super_admin'],
    delete: ['admin', 'super_admin'],
  },
  services: {
    read: ['operator', 'admin', 'super_admin'],
    create: ['admin', 'super_admin'],
    update: ['admin', 'super_admin'],
    delete: ['super_admin'],
  },
  withdrawals: {
    read: ['operator', 'admin', 'super_admin'],
    create: ['admin', 'super_admin'],
    update: ['admin', 'super_admin'],
    delete: ['super_admin'],
  },
  statistics: {
    read: ['operator', 'admin', 'super_admin'],
  },
  translations: {
    read: ['operator', 'admin', 'super_admin'],
    create: ['admin', 'super_admin'],
    update: ['admin', 'super_admin'],
    delete: ['super_admin'],
  },
};

/**
 * Check if admin has required role
 * @param {string[]} allowedRoles - Array of allowed roles
 * @returns {Function} Express middleware
 */
const requireRole = (allowedRoles) => {
  return (req, res, next) => {
    try {
      // Check if admin is authenticated
      if (!req.admin) {
        return res.status(401).json({
          success: false,
          error: {
            code: 'UNAUTHORIZED',
            message: 'Authentication required',
          },
        });
      }

      const adminRole = req.admin.role;

      // Check if admin role is in allowed roles
      const hasPermission = allowedRoles.some(allowedRole => {
        const adminLevel = ROLE_HIERARCHY[adminRole] || 0;
        const requiredLevel = ROLE_HIERARCHY[allowedRole] || 0;
        return adminLevel >= requiredLevel;
      });

      if (!hasPermission) {
        logger.warn(`Access denied for admin ${req.admin.username} (${adminRole}) to endpoint ${req.path}`);
        
        return res.status(403).json({
          success: false,
          error: {
            code: 'FORBIDDEN',
            message: 'Insufficient permissions',
            details: `Required role: ${allowedRoles.join(' or ')}`,
          },
        });
      }

      // Admin has permission, continue
      next();
    } catch (error) {
      logger.error('RBAC middleware error:', error);
      
      return res.status(500).json({
        success: false,
        error: {
          code: 'RBAC_ERROR',
          message: 'Authorization error',
          details: error.message,
        },
      });
    }
  };
};

/**
 * Require super admin role
 */
const requireSuperAdmin = requireRole(['super_admin']);

/**
 * Require admin or higher role
 */
const requireAdmin = requireRole(['admin', 'super_admin']);

/**
 * Require operator or higher role (any authenticated admin)
 */
const requireOperator = requireRole(['operator', 'admin', 'super_admin']);

/**
 * Check if admin has permission for a specific resource and action
 * @param {string} resource - Resource name (e.g., 'users', 'translations')
 * @param {string} action - Action name (e.g., 'read', 'create', 'update', 'delete')
 * @returns {Function} Express middleware
 */
const requirePermission = (resource, action) => {
  return (req, res, next) => {
    try {
      // Check if admin is authenticated
      if (!req.admin) {
        return res.status(401).json({
          success: false,
          error: {
            code: 'UNAUTHORIZED',
            message: 'Authentication required',
          },
        });
      }

      const adminRole = req.admin.role;
      const resourcePermissions = RESOURCE_PERMISSIONS[resource];

      // If resource not defined, deny access
      if (!resourcePermissions) {
        logger.warn(`Unknown resource: ${resource}`);
        return res.status(403).json({
          success: false,
          error: {
            code: 'FORBIDDEN',
            message: 'Resource not found',
          },
        });
      }

      const allowedRoles = resourcePermissions[action];

      // If action not defined for resource, deny access
      if (!allowedRoles) {
        logger.warn(`Unknown action: ${action} for resource: ${resource}`);
        return res.status(403).json({
          success: false,
          error: {
            code: 'FORBIDDEN',
            message: 'Action not permitted',
          },
        });
      }

      // Check if admin role is in allowed roles
      if (!allowedRoles.includes(adminRole)) {
        logger.warn(`Access denied for admin ${req.admin.username} (${adminRole}) to ${action} ${resource}`);
        
        return res.status(403).json({
          success: false,
          error: {
            code: 'FORBIDDEN',
            message: 'Insufficient permissions',
            details: `Required permission: ${resource}:${action}`,
          },
        });
      }

      // Admin has permission, continue
      next();
    } catch (error) {
      logger.error('RBAC permission middleware error:', error);
      
      return res.status(500).json({
        success: false,
        error: {
          code: 'RBAC_ERROR',
          message: 'Authorization error',
          details: error.message,
        },
      });
    }
  };
};

module.exports = {
  requireRole,
  requireSuperAdmin,
  requireAdmin,
  requireOperator,
  requirePermission,
  ROLE_HIERARCHY,
  RESOURCE_PERMISSIONS,
};
