/**
 * ========================================
 * CONFIGURACIÓN DE PERMISOS Y ROLES
 * ========================================
 *
 * Este archivo define:
 * 1. Roles disponibles en el sistema
 * 2. Permisos por rol
 * 3. Rutas y recursos accesibles por rol
 * 4. Metadata para construir menús en el frontend
 *
 * IMPORTANTE: Este archivo puede migrar a BD fácilmente
 * manteniendo la misma estructura.
 */

// ========================================
// DEFINICIÓN DE ROLES
// ========================================
const ROLES = {
  ADMIN: 'admin',
  USER: 'usuario',
  GUEST: 'invitado'
};

// ========================================
// DEFINICIÓN DE RECURSOS
// ========================================
// Cada recurso representa un módulo del sistema
const RESOURCES = {
  // Gestión de usuarios
  USERS: 'users',
  PROFILE: 'profile',

  // Catálogos
  CATEGORIES: 'categories',
  ACTIVITIES: 'activities',
  BADGES: 'badges',
  LEVELS: 'levels',

  // Usuario
  GOALS: 'goals',
  AGENDA: 'agenda',
  ACTIVITY_LOG: 'activity_log',
  NOTIFICATIONS: 'notifications',

  // Métricas
  USER_METRICS: 'user_metrics',
  ADMIN_METRICS: 'admin_metrics',

  // Relaciones
  USER_BADGES: 'user_badges',
  USER_ROLES: 'user_roles'
};

// ========================================
// DEFINICIÓN DE ACCIONES
// ========================================
const ACTIONS = {
  CREATE: 'create',
  READ: 'read',
  UPDATE: 'update',
  DELETE: 'delete',
  LIST: 'list',
  MANAGE: 'manage' // Todas las acciones
};

// ========================================
// PERMISOS POR ROL
// ========================================
// Define qué puede hacer cada rol en cada recurso
const PERMISSIONS = {
  [ROLES.ADMIN]: {
    // El admin tiene acceso total a TODO
    [RESOURCES.USERS]: [ACTIONS.MANAGE],
    [RESOURCES.PROFILE]: [ACTIONS.MANAGE],
    [RESOURCES.CATEGORIES]: [ACTIONS.MANAGE],
    [RESOURCES.ACTIVITIES]: [ACTIONS.MANAGE],
    [RESOURCES.BADGES]: [ACTIONS.MANAGE],
    [RESOURCES.LEVELS]: [ACTIONS.MANAGE],
    [RESOURCES.GOALS]: [ACTIONS.MANAGE],
    [RESOURCES.AGENDA]: [ACTIONS.MANAGE],
    [RESOURCES.ACTIVITY_LOG]: [ACTIONS.MANAGE],
    [RESOURCES.NOTIFICATIONS]: [ACTIONS.MANAGE],
    [RESOURCES.USER_METRICS]: [ACTIONS.MANAGE],
    [RESOURCES.ADMIN_METRICS]: [ACTIONS.MANAGE],
    [RESOURCES.USER_BADGES]: [ACTIONS.MANAGE],
    [RESOURCES.USER_ROLES]: [ACTIONS.MANAGE]
  },

  [ROLES.USER]: {
    // El usuario normal tiene acceso limitado
    [RESOURCES.PROFILE]: [ACTIONS.READ, ACTIONS.UPDATE],

    // Puede VER catálogos pero no modificarlos
    [RESOURCES.CATEGORIES]: [ACTIONS.READ, ACTIONS.LIST],
    [RESOURCES.ACTIVITIES]: [ACTIONS.READ, ACTIONS.LIST],
    [RESOURCES.BADGES]: [ACTIONS.READ, ACTIONS.LIST],
    [RESOURCES.LEVELS]: [ACTIONS.READ, ACTIONS.LIST],

    // Puede gestionar SUS PROPIOS recursos
    [RESOURCES.GOALS]: [ACTIONS.CREATE, ACTIONS.READ, ACTIONS.UPDATE, ACTIONS.DELETE, ACTIONS.LIST],
    [RESOURCES.AGENDA]: [ACTIONS.CREATE, ACTIONS.READ, ACTIONS.UPDATE, ACTIONS.DELETE, ACTIONS.LIST],
    [RESOURCES.ACTIVITY_LOG]: [ACTIONS.CREATE, ACTIONS.READ, ACTIONS.UPDATE, ACTIONS.DELETE, ACTIONS.LIST],
    [RESOURCES.NOTIFICATIONS]: [ACTIONS.READ, ACTIONS.LIST, ACTIONS.UPDATE],

    // Puede ver SUS PROPIAS métricas
    [RESOURCES.USER_METRICS]: [ACTIONS.READ, ACTIONS.LIST],
    [RESOURCES.USER_BADGES]: [ACTIONS.READ, ACTIONS.LIST],

    // NO puede ver métricas de admin
    [RESOURCES.ADMIN_METRICS]: [],
    [RESOURCES.USER_ROLES]: []
  },

  [ROLES.GUEST]: {
    // Invitado solo puede ver catálogos públicos
    [RESOURCES.CATEGORIES]: [ACTIONS.READ, ACTIONS.LIST],
    [RESOURCES.ACTIVITIES]: [ACTIONS.READ, ACTIONS.LIST],
    [RESOURCES.BADGES]: [ACTIONS.READ, ACTIONS.LIST]
  }
};

// ========================================
// CONFIGURACIÓN DE RUTAS
// ========================================
// Define las rutas del sistema con metadata para menús
const ROUTE_CONFIG = [
  // ========== PERFIL ==========
  {
    resource: RESOURCES.PROFILE,
    path: '/api/auth/me',
    method: 'GET',
    requiresAuth: true,
    action: ACTIONS.READ,
    metadata: {
      label: 'Mi Perfil',
      icon: 'user',
      showInMenu: true,
      group: 'Cuenta',
      order: 1
    }
  },
  {
    resource: RESOURCES.PROFILE,
    path: '/api/auth/me/profile',
    method: 'PUT',
    requiresAuth: true,
    action: ACTIONS.UPDATE,
    metadata: {
      showInMenu: false
    }
  },

  // ========== CATÁLOGOS ==========
  {
    resource: RESOURCES.CATEGORIES,
    path: '/api/categorias',
    method: 'GET',
    requiresAuth: false,
    action: ACTIONS.LIST,
    metadata: {
      label: 'Categorías',
      icon: 'folder',
      showInMenu: true,
      group: 'Catálogos',
      order: 10,
      roles: [ROLES.ADMIN, ROLES.USER]
    }
  },
  {
    resource: RESOURCES.CATEGORIES,
    path: '/api/categorias',
    method: 'POST',
    requiresAuth: true,
    action: ACTIONS.CREATE,
    metadata: {
      showInMenu: false,
      roles: [ROLES.ADMIN]
    }
  },

  {
    resource: RESOURCES.ACTIVITIES,
    path: '/api/actividades',
    method: 'GET',
    requiresAuth: false,
    action: ACTIONS.LIST,
    metadata: {
      label: 'Actividades',
      icon: 'activity',
      showInMenu: true,
      group: 'Catálogos',
      order: 11,
      roles: [ROLES.ADMIN, ROLES.USER]
    }
  },
  {
    resource: RESOURCES.ACTIVITIES,
    path: '/api/actividades',
    method: 'POST',
    requiresAuth: true,
    action: ACTIONS.CREATE,
    metadata: {
      showInMenu: false,
      roles: [ROLES.ADMIN]
    }
  },

  {
    resource: RESOURCES.BADGES,
    path: '/api/insignias',
    method: 'GET',
    requiresAuth: false,
    action: ACTIONS.LIST,
    metadata: {
      label: 'Insignias',
      icon: 'award',
      showInMenu: true,
      group: 'Catálogos',
      order: 12,
      roles: [ROLES.ADMIN, ROLES.USER]
    }
  },

  {
    resource: RESOURCES.LEVELS,
    path: '/api/niveles',
    method: 'GET',
    requiresAuth: false,
    action: ACTIONS.LIST,
    metadata: {
      label: 'Niveles',
      icon: 'trending-up',
      showInMenu: true,
      group: 'Catálogos',
      order: 13,
      roles: [ROLES.ADMIN, ROLES.USER]
    }
  },

  // ========== MIS RECURSOS ==========
  {
    resource: RESOURCES.GOALS,
    path: '/api/metas',
    method: 'GET',
    requiresAuth: true,
    action: ACTIONS.LIST,
    metadata: {
      label: 'Mis Metas',
      icon: 'target',
      showInMenu: true,
      group: 'Mi Progreso',
      order: 20,
      roles: [ROLES.USER, ROLES.ADMIN]
    }
  },
  {
    resource: RESOURCES.GOALS,
    path: '/api/metas',
    method: 'POST',
    requiresAuth: true,
    action: ACTIONS.CREATE,
    metadata: {
      showInMenu: false
    }
  },

  {
    resource: RESOURCES.AGENDA,
    path: '/api/agenda',
    method: 'GET',
    requiresAuth: true,
    action: ACTIONS.LIST,
    metadata: {
      label: 'Mi Agenda',
      icon: 'calendar',
      showInMenu: true,
      group: 'Mi Progreso',
      order: 21,
      roles: [ROLES.USER, ROLES.ADMIN]
    }
  },

  {
    resource: RESOURCES.ACTIVITY_LOG,
    path: '/api/registroactividad',
    method: 'GET',
    requiresAuth: true,
    action: ACTIONS.LIST,
    metadata: {
      label: 'Mis Actividades',
      icon: 'list',
      showInMenu: true,
      group: 'Mi Progreso',
      order: 22,
      roles: [ROLES.USER, ROLES.ADMIN]
    }
  },

  {
    resource: RESOURCES.NOTIFICATIONS,
    path: '/api/notificaciones',
    method: 'GET',
    requiresAuth: true,
    action: ACTIONS.LIST,
    metadata: {
      label: 'Notificaciones',
      icon: 'bell',
      showInMenu: true,
      group: 'Mi Progreso',
      order: 23,
      roles: [ROLES.USER, ROLES.ADMIN]
    }
  },

  // ========== MÉTRICAS ==========
  {
    resource: RESOURCES.USER_METRICS,
    path: '/api/metricas',
    method: 'GET',
    requiresAuth: true,
    action: ACTIONS.LIST,
    metadata: {
      label: 'Mis Estadísticas',
      icon: 'bar-chart',
      showInMenu: true,
      group: 'Estadísticas',
      order: 30,
      roles: [ROLES.USER, ROLES.ADMIN]
    }
  },

  {
    resource: RESOURCES.USER_BADGES,
    path: '/api/usuario-insignias',
    method: 'GET',
    requiresAuth: true,
    action: ACTIONS.LIST,
    metadata: {
      label: 'Mis Insignias',
      icon: 'award',
      showInMenu: true,
      group: 'Estadísticas',
      order: 31,
      roles: [ROLES.USER, ROLES.ADMIN]
    }
  },

  // ========== ADMIN ==========
  {
    resource: RESOURCES.ADMIN_METRICS,
    path: '/api/admin/metrics',
    method: 'GET',
    requiresAuth: true,
    action: ACTIONS.READ,
    metadata: {
      label: 'Métricas del Sistema',
      icon: 'pie-chart',
      showInMenu: true,
      group: 'Administración',
      order: 100,
      roles: [ROLES.ADMIN]
    }
  },

  {
    resource: RESOURCES.USER_ROLES,
    path: '/api/usuario-roles',
    method: 'GET',
    requiresAuth: true,
    action: ACTIONS.LIST,
    metadata: {
      label: 'Gestión de Roles',
      icon: 'shield',
      showInMenu: true,
      group: 'Administración',
      order: 101,
      roles: [ROLES.ADMIN]
    }
  }
];

// ========================================
// FUNCIONES DE AYUDA
// ========================================

/**
 * Verifica si un rol tiene permiso para una acción en un recurso
 * @param {string} role - El rol a verificar
 * @param {string} resource - El recurso
 * @param {string} action - La acción
 * @returns {boolean}
 */
function hasPermission(role, resource, action) {
  const rolePermissions = PERMISSIONS[role];
  if (!rolePermissions) return false;

  const resourcePermissions = rolePermissions[resource];
  if (!resourcePermissions) return false;

  // Si tiene permiso MANAGE, tiene todos los permisos
  if (resourcePermissions.includes(ACTIONS.MANAGE)) return true;

  // Sino, verificar la acción específica
  return resourcePermissions.includes(action);
}

/**
 * Obtiene todas las rutas accesibles para un rol
 * @param {string} role - El rol
 * @param {boolean} onlyMenuItems - Si solo devolver rutas que se muestran en menú
 * @returns {Array}
 */
function getRoutesForRole(role, onlyMenuItems = false) {
  return ROUTE_CONFIG.filter(route => {
    // Verificar si tiene permiso para esta ruta
    const hasAccess = hasPermission(role, route.resource, route.action);
    if (!hasAccess) return false;

    // Si solo queremos items de menú
    if (onlyMenuItems && !route.metadata.showInMenu) return false;

    // Verificar si la ruta especifica roles permitidos
    if (route.metadata.roles && !route.metadata.roles.includes(role)) {
      return false;
    }

    return true;
  });
}

/**
 * Construye el menú para un rol específico
 * @param {string} role - El rol
 * @returns {Object} - Menú agrupado
 */
function buildMenuForRole(role) {
  const routes = getRoutesForRole(role, true);

  // Agrupar por grupo
  const grouped = {};
  routes.forEach(route => {
    const group = route.metadata.group || 'Otros';
    if (!grouped[group]) {
      grouped[group] = [];
    }
    grouped[group].push({
      label: route.metadata.label,
      icon: route.metadata.icon,
      path: route.path,
      method: route.method,
      order: route.metadata.order || 999
    });
  });

  // Ordenar items dentro de cada grupo
  Object.keys(grouped).forEach(group => {
    grouped[group].sort((a, b) => a.order - b.order);
  });

  return grouped;
}

/**
 * Obtiene todos los permisos de un rol
 * @param {string} role - El rol
 * @returns {Object}
 */
function getPermissionsForRole(role) {
  return PERMISSIONS[role] || {};
}

/**
 * Verifica si un usuario (con sus roles) puede acceder a una ruta
 * @param {Array} userRoles - Array de roles del usuario
 * @param {string} resource - Recurso
 * @param {string} action - Acción
 * @returns {boolean}
 */
function canAccess(userRoles, resource, action) {
  if (!Array.isArray(userRoles) || userRoles.length === 0) return false;

  // Si tiene al menos un rol con permiso, puede acceder
  return userRoles.some(role => hasPermission(role, resource, action));
}

// ========================================
// EXPORTACIÓN
// ========================================
module.exports = {
  ROLES,
  RESOURCES,
  ACTIONS,
  PERMISSIONS,
  ROUTE_CONFIG,
  hasPermission,
  getRoutesForRole,
  buildMenuForRole,
  getPermissionsForRole,
  canAccess
};
