import { Response } from 'express';
import { z } from 'zod';
import { prisma } from '../index';
import logger from '../utils/logger';
import { createError, asyncHandler } from '../middlewares/errorHandler';
import { AuthenticatedRequest } from '../middlewares/auth';
import { NotificationService } from '../services/notificationService';

// Validation schemas
const paginationSchema = z.object({
  page: z.coerce.number().min(1).optional(),
  limit: z.coerce.number().min(1).max(100).optional(),
  isRead: z.coerce.boolean().optional(),
  type: z.enum(['BOT_ASSIGNED']).optional(),
});

const uuidParamSchema = z.object({
  id: z.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i, 'Invalid notification ID'),
});

type PaginationInput = z.infer<typeof paginationSchema>;
type UuidParamInput = z.infer<typeof uuidParamSchema>;

/**
 * Get notifications for the authenticated user
 */
export const getUserNotifications = asyncHandler(async (req: AuthenticatedRequest, res: Response) => {
  const validatedParams: PaginationInput = paginationSchema.parse(req.query);
  const { page = 1, limit = 20, isRead, type } = validatedParams;

  if (!req.user) {
    throw createError('Authentication required', 401);
  }

  const result = await NotificationService.getUserNotifications(
    req.user.id,
    page,
    limit,
    { isRead, type }
  );

  logger.info('User notifications retrieved successfully', {
    userId: req.user.id,
    page,
    limit,
    total: result.pagination.total,
    unreadCount: result.notifications.filter(n => !n.isRead).length,
  });

  res.status(200).json({
    success: true,
    message: 'Notifications retrieved successfully',
    data: result,
  });
});

/**
 * Get unread notifications count for the authenticated user
 */
export const getUnreadCount = asyncHandler(async (req: AuthenticatedRequest, res: Response) => {
  if (!req.user) {
    throw createError('Authentication required', 401);
  }

  const count = await NotificationService.getUnreadCount(req.user.id);

  logger.info('Unread notifications count retrieved', {
    userId: req.user.id,
    count,
  });

  res.status(200).json({
    success: true,
    message: 'Unread count retrieved successfully',
    data: {
      unreadCount: count,
    },
  });
});

/**
 * Mark a specific notification as read
 */
export const markAsRead = asyncHandler(async (req: AuthenticatedRequest, res: Response) => {
  const { id }: UuidParamInput = uuidParamSchema.parse(req.params);

  if (!req.user) {
    throw createError('Authentication required', 401);
  }

  const notification = await NotificationService.markAsRead(id, req.user.id);

  logger.info('Notification marked as read', {
    userId: req.user.id,
    notificationId: id,
  });

  res.status(200).json({
    success: true,
    message: 'Notification marked as read successfully',
    data: notification,
  });
});

/**
 * Mark all notifications as read for the authenticated user
 */
export const markAllAsRead = asyncHandler(async (req: AuthenticatedRequest, res: Response) => {
  if (!req.user) {
    throw createError('Authentication required', 401);
  }

  const result = await NotificationService.markAllAsRead(req.user.id);

  logger.info('All notifications marked as read', {
    userId: req.user.id,
    updatedCount: result.count,
  });

  res.status(200).json({
    success: true,
    message: 'All notifications marked as read successfully',
    data: {
      updatedCount: result.count,
    },
  });
});

/**
 * Delete a notification
 */
export const deleteNotification = asyncHandler(async (req: AuthenticatedRequest, res: Response) => {
  const { id }: UuidParamInput = uuidParamSchema.parse(req.params);

  if (!req.user) {
    throw createError('Authentication required', 401);
  }

  // Verify the notification belongs to the user
  const notification = await prisma.notification.findFirst({
    where: {
      id,
      userId: req.user.id,
    },
  });

  if (!notification) {
    throw createError('Notification not found', 404);
  }

  await prisma.notification.delete({
    where: {
      id,
    },
  });

  logger.info('Notification deleted', {
    userId: req.user.id,
    notificationId: id,
  });

  res.status(200).json({
    success: true,
    message: 'Notification deleted successfully',
  });
});
