import { Router } from 'express';
import { RBACService, Role, Permission } from '../services/rbac.service';
import { requirePermission, requireAdmin, AuthorizedRequest, getUserPermissionsForResponse } from '../middleware/authorization';
import { authenticateToken } from '../middleware/auth';

const router = Router();

// Apply authentication to all RBAC routes
router.use(authenticateToken);

/**
 * Get all permissions
 */
router.get('/permissions', requirePermission('admin:roles'), (req, res) => {
  try {
    const permissions = RBACService.getAllPermissions();
    res.json({
      success: true,
      permissions: permissions.map(p => ({
        id: p.id,
        name: p.name,
        description: p.description,
        resource: p.resource,
        action: p.action
      }))
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      error: 'Failed to fetch permissions'
    });
  }
});

/**
 * Get all roles
 */
router.get('/roles', requirePermission('admin:roles'), (req, res) => {
  try {
    const roles = RBACService.getAllRoles();
    res.json({
      success: true,
      roles: roles.map(r => ({
        id: r.id,
        name: r.name,
        description: r.description,
        permissions: r.permissions,
        isSystemRole: r.isSystemRole
      }))
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      error: 'Failed to fetch roles'
    });
  }
});

/**
 * Get specific role
 */
router.get('/roles/:roleId', requirePermission('admin:roles'), (req, res) => {
  try {
    const { roleId } = req.params;
    const role = RBACService.getRole(roleId);
    
    if (!role) {
      return res.status(404).json({
        success: false,
        error: 'Role not found'
      });
    }
    
    res.json({
      success: true,
      role: {
        id: role.id,
        name: role.name,
        description: role.description,
        permissions: role.permissions,
        isSystemRole: role.isSystemRole
      }
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      error: 'Failed to fetch role'
    });
  }
});

/**
 * Create new role
 */
router.post('/roles', requirePermission('admin:roles'), (req, res) => {
  try {
    const { id, name, description, permissions } = req.body;
    
    if (!id || !name || !Array.isArray(permissions)) {
      return res.status(400).json({
        success: false,
        error: 'Missing required fields: id, name, permissions'
      });
    }
    
    const role: Role = {
      id,
      name,
      description: description || '',
      permissions,
      isSystemRole: false
    };
    
    const created = RBACService.createRole(role);
    
    if (!created) {
      return res.status(409).json({
        success: false,
        error: 'Role already exists or invalid permissions'
      });
    }
    
    res.status(201).json({
      success: true,
      message: 'Role created successfully',
      role: {
        id: role.id,
        name: role.name,
        description: role.description,
        permissions: role.permissions,
        isSystemRole: role.isSystemRole
      }
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      error: 'Failed to create role'
    });
  }
});

/**
 * Create new permission
 */
router.post('/permissions', requirePermission('admin:roles'), (req, res) => {
  try {
    const { id, name, description, resource, action } = req.body;
    
    if (!id || !name || !resource || !action) {
      return res.status(400).json({
        success: false,
        error: 'Missing required fields: id, name, resource, action'
      });
    }
    
    const permission: Permission = {
      id,
      name,
      description: description || '',
      resource,
      action
    };
    
    const created = RBACService.createPermission(permission);
    
    if (!created) {
      return res.status(409).json({
        success: false,
        error: 'Permission already exists'
      });
    }
    
    res.status(201).json({
      success: true,
      message: 'Permission created successfully',
      permission: {
        id: permission.id,
        name: permission.name,
        description: permission.description,
        resource: permission.resource,
        action: permission.action
      }
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      error: 'Failed to create permission'
    });
  }
});

/**
 * Assign role to user
 */
router.post('/users/:userId/roles', requirePermission('admin:users'), (req, res) => {
  try {
    const { userId } = req.params;
    const { roleId, projectId } = req.body;
    const grantedBy = (req as AuthorizedRequest).user?.id;
    
    if (!roleId) {
      return res.status(400).json({
        success: false,
        error: 'Role ID is required'
      });
    }
    
    const assigned = RBACService.assignRole(userId, roleId, projectId, grantedBy);
    
    if (!assigned) {
      return res.status(409).json({
        success: false,
        error: 'Role assignment failed - role may not exist or user already has this role'
      });
    }
    
    res.json({
      success: true,
      message: 'Role assigned successfully'
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      error: 'Failed to assign role'
    });
  }
});

/**
 * Remove role from user
 */
router.delete('/users/:userId/roles/:roleId', requirePermission('admin:users'), (req, res) => {
  try {
    const { userId, roleId } = req.params;
    const { projectId } = req.query;
    
    const removed = RBACService.removeRole(userId, roleId, projectId as string);
    
    if (!removed) {
      return res.status(404).json({
        success: false,
        error: 'Role assignment not found'
      });
    }
    
    res.json({
      success: true,
      message: 'Role removed successfully'
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      error: 'Failed to remove role'
    });
  }
});

/**
 * Get user's roles and permissions
 */
router.get('/users/:userId/permissions', requirePermission('admin:users'), (req, res) => {
  try {
    const { userId } = req.params;
    const { projectId } = req.query;
    
    const userPermissions = getUserPermissionsForResponse(userId, projectId as string);
    
    res.json({
      success: true,
      userId,
      projectId: projectId || null,
      ...userPermissions
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      error: 'Failed to fetch user permissions'
    });
  }
});

/**
 * Get current user's permissions
 */
router.get('/me/permissions', (req, res) => {
  try {
    const userId = (req as AuthorizedRequest).user?.id;
    const { projectId } = req.query;
    
    if (!userId) {
      return res.status(401).json({
        success: false,
        error: 'Authentication required'
      });
    }
    
    const userPermissions = getUserPermissionsForResponse(userId, projectId as string);
    
    res.json({
      success: true,
      userId,
      projectId: projectId || null,
      ...userPermissions
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      error: 'Failed to fetch permissions'
    });
  }
});

/**
 * Check if user has specific permission
 */
router.post('/check-permission', (req, res) => {
  try {
    const userId = (req as AuthorizedRequest).user?.id;
    const { permissionId, projectId } = req.body;
    
    if (!userId) {
      return res.status(401).json({
        success: false,
        error: 'Authentication required'
      });
    }
    
    if (!permissionId) {
      return res.status(400).json({
        success: false,
        error: 'Permission ID is required'
      });
    }
    
    const hasPermission = RBACService.hasPermission(userId, permissionId, projectId);
    
    res.json({
      success: true,
      hasPermission,
      userId,
      permissionId,
      projectId: projectId || null
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      error: 'Failed to check permission'
    });
  }
});

/**
 * Get project members
 */
router.get('/projects/:projectId/members', requirePermission('project:read', 'projectId'), (req, res) => {
  try {
    const { projectId } = req.params;
    
    const members = RBACService.getProjectMembers(projectId);
    
    res.json({
      success: true,
      projectId,
      members: members.map(member => ({
        userId: member.userId,
        roles: member.roles.map(role => ({
          roleId: role.roleId,
          grantedAt: role.grantedAt,
          grantedBy: role.grantedBy
        }))
      }))
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      error: 'Failed to fetch project members'
    });
  }
});

export default router;