import express from 'express';
import User from '../../models/User.js';
import TeamPermissions from '../../models/TeamPermissions.js';
import { authenticateToken, authorizeRole } from '../../middleware/auth.js';
import RedisService from '../../services/RedisService.js';

const router = express.Router();

/**
 * POST /api/admin/roles/assign
 * Assign a role to a user
 */
router.post('/assign',
  authenticateToken,
  authorizeRole(['admin']),
  async (req, res) => {
    try {
      const { user_id, role, team_id } = req.body;

      const validRoles = ['admin', 'ui_team', 'ux_team', 'qa_team'];
      if (!validRoles.includes(role)) {
        return res.status(400).json({
          status: 'error',
          code: 'INVALID_ROLE',
          message: 'Invalid role provided',
          data: null
        });
      }

      const user = await User.findByPk(user_id);
      if (!user) {
        return res.status(404).json({
          status: 'error',
          code: 'USER_NOT_FOUND',
          message: 'User not found',
          data: null
        });
      }

      user.role = role;
      if (team_id !== undefined) user.team_id = team_id;
      await user.save();

      return res.json({
        status: 'success',
        code: 'ROLE_ASSIGNED',
        message: 'Role assigned successfully',
        data: {
          id: user.id,
          email: user.email,
          role: user.role,
          team_id: user.team_id
        }
      });
    } catch (error) {
      console.error('Assign Role Error:', error);
      return res.status(500).json({
        status: 'error',
        code: 'SERVER_ERROR',
        message: 'Failed to assign role',
        data: null
      });
    }
  }
);

/**
 * GET /api/admin/roles/permissions/:role
 * Get all permissions for a specific role
 */
router.get('/permissions/:role',
  authenticateToken,
  async (req, res) => {
    try {
      const requestedRole = req.params.role;

      const validRoles = ['admin', 'ui_team', 'ux_team', 'qa_team'];
      if (!validRoles.includes(requestedRole)) {
        return res.status(400).json({
          status: 'error',
          code: 'INVALID_ROLE',
          message: 'Invalid role',
          data: null
        });
      }

      // Users can view their own role's permissions, or Admin can view any
      if (req.user.role !== 'admin' && req.user.role !== requestedRole) {
        return res.status(403).json({
          status: 'error',
          code: 'FORBIDDEN',
          message: 'You can only view your own role permissions',
          data: null
        });
      }

      const permissions = await TeamPermissions.findAll({
        where: { role: requestedRole }
      });

      return res.json({
        status: 'success',
        code: 'PERMISSIONS_RETRIEVED',
        message: 'Permissions retrieved successfully',
        data: { role: requestedRole, permissions }
      });
    } catch (error) {
      console.error('Get Permissions Error:', error);
      return res.status(500).json({
        status: 'error',
        code: 'SERVER_ERROR',
        message: 'Failed to fetch permissions',
        data: null
      });
    }
  }
);

/**
 * PUT /api/admin/roles/permissions/:role
 * Upsert permissions (Enable/Disable)
 */
router.put('/permissions/:role',
  authenticateToken,
  authorizeRole(['admin']),
  async (req, res) => {
    try {
      const role = req.params.role;
      const { permission, resource, action, enabled } = req.body;

      const validRoles = ['admin', 'ui_team', 'ux_team', 'qa_team'];
      if (!validRoles.includes(role)) {
        return res.status(400).json({
          status: 'error',
          code: 'INVALID_ROLE',
          message: 'Invalid role',
          data: null
        });
      }

      if (enabled === false) {
        // Delete permission if it exists
        await TeamPermissions.destroy({
          where: { role, resource, action }
        });

        // Invalidate cache for this role
        await RedisService.invalidateRole(role);

        return res.json({
          status: 'success',
          code: 'PERMISSION_DISABLED',
          message: 'Permission disabled (removed)',
          data: null
        });
      } else {
        // Create or Update
        const [perm, created] = await TeamPermissions.findOrCreate({
          where: { role, resource, action },
          defaults: { permission, role, resource, action }
        });

        // Invalidate cache for this role
        await RedisService.invalidateRole(role);

        return res.json({
          status: 'success',
          code: created ? 'PERMISSION_CREATED' : 'PERMISSION_EXISTS',
          message: created ? 'Permission created' : 'Permission already exists',
          data: perm
        });
      }
    } catch (error) {
      console.error('Update Permission Error:', error);
      return res.status(500).json({
        status: 'error',
        code: 'SERVER_ERROR',
        message: 'Failed to update permission',
        data: null
      });
    }
  }
);

/**
 * GET /api/admin/users/:user_id/permissions
 * Get effective permissions for a specific user
 */
router.get('/users/:user_id/permissions',
  authenticateToken,
  async (req, res) => {
    try {
      const { user_id } = req.params;

      // Security check: Admin or Self only
      if (req.user.role !== 'admin' && req.user.id !== user_id) {
        return res.status(403).json({
          status: 'error',
          code: 'FORBIDDEN',
          message: 'Forbidden',
          data: null
        });
      }

      const user = await User.findByPk(user_id);
      if (!user) {
        return res.status(404).json({
          status: 'error',
          code: 'USER_NOT_FOUND',
          message: 'User not found',
          data: null
        });
      }

      // If user is Admin, they implicitly have all permissions
      if (user.role === 'admin') {
        return res.json({
          status: 'success',
          code: 'PERMISSIONS_RETRIEVED',
          message: 'Admin has all permissions',
          data: {
            user_id,
            role: user.role,
            isAdmin: true,
            permissions: ['*'] // Represents all access
          }
        });
      }

      const permissions = await TeamPermissions.findAll({
        where: { role: user.role }
      });

      return res.json({
        status: 'success',
        code: 'PERMISSIONS_RETRIEVED',
        message: 'Permissions retrieved successfully',
        data: {
          user_id,
          role: user.role,
          isAdmin: false,
          permissions
        }
      });
    } catch (error) {
      console.error('User Permissions Error:', error);
      return res.status(500).json({
        status: 'error',
        code: 'SERVER_ERROR',
        message: 'Failed to fetch user permissions',
        data: null
      });
    }
  }
);

export default router;
