import { Router } from 'express';
import { z } from 'zod';
import { NotificationController } from './notificationController';
import { validate, validateMultiple } from '../api/middleware/validation.middleware';
import { authenticateToken, requirePermission } from '../api/middleware/rbac.middleware';
import { generalLimiter, strictLimiter } from '../api/middleware/rateLimit.middleware';
import { Permission } from '../api/services/rbac.service';
import { NotificationType, NotificationPriority } from './notificationService';

const router = Router();
const notificationController = new NotificationController();

// Validation schemas
const GetNotificationsSchema = z.object({
  page: z.coerce.number().int().min(1).optional(),
  limit: z.coerce.number().int().min(1).max(100).optional(),
  unreadOnly: z.coerce.boolean().optional()
});

const PreferencesSchema = z.object({
  email: z.object({
    enabled: z.boolean(),
    frequency: z.enum(['instant', 'hourly', 'daily', 'weekly']),
    types: z.array(z.nativeEnum(NotificationType))
  }).optional(),
  realtime: z.object({
    enabled: z.boolean(),
    types: z.array(z.nativeEnum(NotificationType)),
    sound: z.boolean(),
    desktop: z.boolean()
  }).optional(),
  doNotDisturb: z.object({
    enabled: z.boolean(),
    startTime: z.string().regex(/^\d{2}:\d{2}$/).optional(),
    endTime: z.string().regex(/^\d{2}:\d{2}$/).optional(),
    timezone: z.string().optional()
  }).optional()
});

const SubscriptionSchema = z.object({
  types: z.array(z.nativeEnum(NotificationType)).min(1)
});

const TestNotificationSchema = z.object({
  userId: z.string().uuid(),
  type: z.nativeEnum(NotificationType).optional(),
  priority: z.nativeEnum(NotificationPriority).optional(),
  title: z.string().max(200).optional(),
  message: z.string().max(1000).optional()
});

const CleanupSchema = z.object({
  daysToKeep: z.number().int().min(1).max(365).optional()
});

/**
 * @route   GET /api/notifications
 * @desc    Get user's notifications
 * @access  Protected
 */
router.get(
  '/',
  authenticateToken,
  generalLimiter,
  validate(GetNotificationsSchema, 'query'),
  (req: any, res) => notificationController.getNotifications(req, res)
);

/**
 * @route   PUT /api/notifications/:notificationId/read
 * @desc    Mark notification as read
 * @access  Protected
 */
router.put(
  '/:notificationId/read',
  authenticateToken,
  strictLimiter,
  validate(z.object({ notificationId: z.string().uuid() }), 'params'),
  (req: any, res) => notificationController.markAsRead(req, res)
);

/**
 * @route   PUT /api/notifications/read-all
 * @desc    Mark all notifications as read
 * @access  Protected
 */
router.put(
  '/read-all',
  authenticateToken,
  strictLimiter,
  (req: any, res) => notificationController.markAllAsRead(req, res)
);

/**
 * @route   GET /api/notifications/preferences
 * @desc    Get notification preferences
 * @access  Protected
 */
router.get(
  '/preferences',
  authenticateToken,
  generalLimiter,
  (req: any, res) => notificationController.getPreferences(req, res)
);

/**
 * @route   PUT /api/notifications/preferences
 * @desc    Update notification preferences
 * @access  Protected
 */
router.put(
  '/preferences',
  authenticateToken,
  strictLimiter,
  validate(PreferencesSchema, 'body'),
  (req: any, res) => notificationController.updatePreferences(req, res)
);

/**
 * @route   POST /api/notifications/subscribe
 * @desc    Subscribe to notification types
 * @access  Protected
 */
router.post(
  '/subscribe',
  authenticateToken,
  strictLimiter,
  validate(SubscriptionSchema, 'body'),
  (req: any, res) => notificationController.subscribe(req, res)
);

/**
 * @route   POST /api/notifications/unsubscribe
 * @desc    Unsubscribe from notification types
 * @access  Protected
 */
router.post(
  '/unsubscribe',
  authenticateToken,
  strictLimiter,
  validate(SubscriptionSchema, 'body'),
  (req: any, res) => notificationController.unsubscribe(req, res)
);

/**
 * @route   POST /api/notifications/test
 * @desc    Send test notification (admin only)
 * @access  Protected - Admin only
 */
router.post(
  '/test',
  authenticateToken,
  requirePermission(Permission.MANAGE_SYSTEM),
  strictLimiter,
  validate(TestNotificationSchema, 'body'),
  (req: any, res) => notificationController.sendTestNotification(req, res)
);

/**
 * @route   POST /api/notifications/cleanup
 * @desc    Clean up old notifications (admin only)
 * @access  Protected - Admin only
 */
router.post(
  '/cleanup',
  authenticateToken,
  requirePermission(Permission.MANAGE_SYSTEM),
  strictLimiter,
  validate(CleanupSchema, 'body'),
  (req: any, res) => notificationController.cleanupNotifications(req, res)
);

export default router;