import { Router } from 'express';
import { z } from 'zod';
import { AssignmentController } from '../controllers/assignment.controller';
import { validate, validateMultiple } from '../middleware/validation.middleware';
import { authenticateToken, requirePermission, requireTaskAccess, requireTaskModify } from '../middleware/rbac.middleware';
import { generalLimiter, strictLimiter } from '../middleware/rateLimit.middleware';
import { Permission } from '../services/rbac.service';

const router = Router();
const assignmentController = new AssignmentController();

// Validation schemas
const AssignTaskSchema = z.object({
  taskId: z.string().uuid(),
  assigneeId: z.string().uuid(),
  dueDate: z.string().datetime().optional(),
  workloadPoints: z.number().int().min(1).max(100).optional(),
  notes: z.string().max(500).optional()
});

const ReassignTaskSchema = z.object({
  taskId: z.string().uuid(),
  newAssigneeId: z.string().uuid(),
  reason: z.string().max(500).optional()
});

const BatchAssignSchema = z.object({
  assignments: z.array(z.object({
    taskId: z.string().uuid(),
    assigneeId: z.string().uuid(),
    dueDate: z.string().datetime().optional(),
    workloadPoints: z.number().int().min(1).max(100).optional()
  })).min(1).max(50)
});

const GetAssignedTasksSchema = z.object({
  includeCompleted: z.coerce.boolean().optional(),
  projectId: z.string().uuid().optional(),
  status: z.string().optional(),
  sort: z.string().optional(),
  limit: z.coerce.number().int().min(1).max(1000).optional()
});

const GetRecommendationsSchema = z.object({
  maxRecommendations: z.coerce.number().int().min(1).max(20).optional(),
  projectTeamOnly: z.coerce.boolean().optional()
});

/**
 * @route   POST /api/assignments/assign
 * @desc    Assign a task to a user
 * @access  Protected - Requires ASSIGN_TASK permission
 */
router.post(
  '/assign',
  authenticateToken,
  requirePermission(Permission.ASSIGN_TASK),
  strictLimiter,
  validate(AssignTaskSchema, 'body'),
  (req: any, res) => assignmentController.assignTask(req, res)
);

/**
 * @route   POST /api/assignments/reassign
 * @desc    Reassign a task to a different user
 * @access  Protected - Requires ASSIGN_TASK permission
 */
router.post(
  '/reassign',
  authenticateToken,
  requirePermission(Permission.ASSIGN_TASK),
  strictLimiter,
  validate(ReassignTaskSchema, 'body'),
  (req: any, res) => assignmentController.reassignTask(req, res)
);

/**
 * @route   DELETE /api/assignments/:taskId
 * @desc    Unassign a task
 * @access  Protected - Requires ASSIGN_TASK permission
 */
router.delete(
  '/:taskId',
  authenticateToken,
  requirePermission(Permission.ASSIGN_TASK),
  strictLimiter,
  validate(z.object({ taskId: z.string().uuid() }), 'params'),
  (req: any, res) => assignmentController.unassignTask(req, res)
);

/**
 * @route   GET /api/assignments/user/:userId
 * @desc    Get tasks assigned to a user
 * @access  Protected - User can view their own or requires VIEW_USERS permission
 */
router.get(
  '/user/:userId',
  authenticateToken,
  generalLimiter,
  validateMultiple({
    params: z.object({ userId: z.string().uuid() }),
    query: GetAssignedTasksSchema
  }),
  (req: any, res) => assignmentController.getAssignedTasks(req, res)
);

/**
 * @route   GET /api/assignments/workload/:userId
 * @desc    Get workload summary for a user
 * @access  Protected - User can view their own or requires VIEW_USERS permission
 */
router.get(
  '/workload/:userId',
  authenticateToken,
  generalLimiter,
  validate(z.object({ userId: z.string().uuid() }), 'params'),
  (req: any, res) => assignmentController.getWorkloadSummary(req, res)
);

/**
 * @route   GET /api/assignments/recommendations/:taskId
 * @desc    Get assignment recommendations for a task
 * @access  Protected - Requires ASSIGN_TASK permission
 */
router.get(
  '/recommendations/:taskId',
  authenticateToken,
  requirePermission(Permission.ASSIGN_TASK),
  generalLimiter,
  validateMultiple({
    params: z.object({ taskId: z.string().uuid() }),
    query: GetRecommendationsSchema
  }),
  (req: any, res) => assignmentController.getAssignmentRecommendations(req, res)
);

/**
 * @route   POST /api/assignments/batch
 * @desc    Batch assign multiple tasks
 * @access  Protected - Requires ASSIGN_TASK permission
 */
router.post(
  '/batch',
  authenticateToken,
  requirePermission(Permission.ASSIGN_TASK),
  strictLimiter,
  validate(BatchAssignSchema, 'body'),
  (req: any, res) => assignmentController.batchAssignTasks(req, res)
);

/**
 * @route   POST /api/assignments/auto-balance/:projectId
 * @desc    Auto-balance workload across project team
 * @access  Protected - Requires ASSIGN_TASK and MANAGE_PROJECT_MEMBERS permissions
 */
router.post(
  '/auto-balance/:projectId',
  authenticateToken,
  requirePermission(Permission.ASSIGN_TASK),
  strictLimiter,
  validate(z.object({ projectId: z.string().uuid() }), 'params'),
  (req: any, res) => assignmentController.autoBalanceWorkload(req, res)
);

export default router;