import { Request, Response } from 'express';
import { ValidationUtils, NotificationValidation } from '../../validations';
import { NotificationService } from './NotificationService';
import { asyncHandler } from '../../utils/asyncHandler';
import { UniResponse } from '../../lib/UniResponse';
import { StatusCode } from '../../lib/StatusCode';

// Extend Request interface to include user
interface AuthenticatedRequest extends Request {
  user?: {
    userId: string;
    email: string;
    role: string;
  };
}

export class NotificationController {
  // ========= GET ALL NOTIFICATION ================
  public static getNotifications = asyncHandler(
    async (req: AuthenticatedRequest, res: Response) => {


      console.log(`============= USER ID ======================`)
      console.log(req?.user?.userId)
      console.log(`============= USER ID ======================`)


      const userId = req.user?.userId;
      if (!userId) {
        return res
          .status(StatusCode.UNAUTHORIZED)
          .json(
            UniResponse.Error('User not authenticated', null, StatusCode.UNAUTHORIZED)
          );
      }

      const { page, limit, is_read, type } = req.query;
      const result = await NotificationService.getNotifications(
        userId,
        page ? Number(page) : 1,
        limit ? Number(limit) : Number.MAX_SAFE_INTEGER, // Return all notifications by default
        {
          is_read: is_read ? is_read === 'true' : undefined,
          type: type as string | undefined,
        }
      );

      return res
        .status(StatusCode.OK)
        .json(
          UniResponse.Success(
            'Notifications retrieved successfully',
            result,
            StatusCode.OK
          )
        );
    }
  );

  // ======== MARK AS READ ===============
  public static markAsRead = asyncHandler(
    async (req: AuthenticatedRequest, res: Response) => {
      const validation = NotificationValidation.markAsRead.validate(req.params);
      if (!ValidationUtils.isValidationSuccess(validation)) {
        return res
          .status(StatusCode.BAD_REQUEST)
          .json(
            UniResponse.Error(
              ValidationUtils.formatValidationError(validation.error),
              null,
              StatusCode.BAD_REQUEST
            )
          );
      }

      const userId = req.user?.userId;
      if (!userId) {
        return res
          .status(StatusCode.UNAUTHORIZED)
          .json(
            UniResponse.Error('User not authenticated', null, StatusCode.UNAUTHORIZED)
          );
      }

      const { id } = ValidationUtils.getValidatedData(validation);
      const notification = await NotificationService.markAsRead(id as any, userId);

      if (!notification) {
        return res
          .status(StatusCode.NOT_FOUND)
          .json(
            UniResponse.Error('Notification not found', null, StatusCode.NOT_FOUND)
          );
      }

      return res
        .status(StatusCode.OK)
        .json(
          UniResponse.Success(
            'Notification marked as read',
            notification,
            StatusCode.OK
          )
        );
    }
  );


  // ======== MARK ALL READ =============
  public static markAllAsRead = asyncHandler(
    async (req: AuthenticatedRequest, res: Response) => {
      const userId = req.user?.userId;
      if (!userId) {
        return res
          .status(StatusCode.UNAUTHORIZED)
          .json(
            UniResponse.Error('User not authenticated', null, StatusCode.UNAUTHORIZED)
          );
      }

      const count = await NotificationService.markAllAsRead(userId);

      return res
        .status(StatusCode.OK)
        .json(
          UniResponse.Success(
            `${count} notifications marked as read`,
            { count },
            StatusCode.OK
          )
        );
    }
  );


  // ============ DELETE NOTIFICATION =========
  public static deleteNotification = asyncHandler(
    async (req: AuthenticatedRequest, res: Response) => {
      const validation = NotificationValidation.deleteNotification.validate(req.params);
      if (!ValidationUtils.isValidationSuccess(validation)) {
        return res
          .status(StatusCode.BAD_REQUEST)
          .json(
            UniResponse.Error(
              ValidationUtils.formatValidationError(validation.error),
              null,
              StatusCode.BAD_REQUEST
            )
          );
      }

      const userId = req.user?.userId;
      if (!userId) {
        return res
          .status(StatusCode.UNAUTHORIZED)
          .json(
            UniResponse.Error('User not authenticated', null, StatusCode.UNAUTHORIZED)
          );
      }

      const { id } = ValidationUtils.getValidatedData(validation);
      const deleted = await NotificationService.deleteNotification(id as any, userId);

      if (!deleted) {
        return res
          .status(StatusCode.NOT_FOUND)
          .json(
            UniResponse.Error('Notification not found', null, StatusCode.NOT_FOUND)
          );
      }

      return res
        .status(StatusCode.OK)
        .json(
          UniResponse.Success(
            'Notification deleted successfully',
            undefined,
            StatusCode.OK
          )
        );
    }
  );


  // ======== GET UN READ COUNT ==============
  public static getUnreadCount = asyncHandler(
    async (req: AuthenticatedRequest, res: Response) => {
      const userId = req.user?.userId;
      if (!userId) {
        return res
          .status(StatusCode.UNAUTHORIZED)
          .json(
            UniResponse.Error('User not authenticated', null, StatusCode.UNAUTHORIZED)
          );
      }

      const count = await NotificationService.getUnreadCount(userId);

      return res
        .status(StatusCode.OK)
        .json(
          UniResponse.Success(
            'Unread count retrieved successfully',
            { count },
            StatusCode.OK
          )
        );
    }
  );


  // ============ CREATE NOTIFICATION ======
  public static createNotification = asyncHandler(
    async (req: AuthenticatedRequest, res: Response) => {
      const validation = NotificationValidation.createNotification.validate(req.body);
      if (!ValidationUtils.isValidationSuccess(validation)) {
        return res
          .status(StatusCode.BAD_REQUEST)
          .json(
            UniResponse.Error(
              ValidationUtils.formatValidationError(validation.error),
              null,
              StatusCode.BAD_REQUEST
            )
          );
      }

      const userId = req.user?.userId;
      if (!userId) {
        return res
          .status(StatusCode.UNAUTHORIZED)
          .json(
            UniResponse.Error('User not authenticated', null, StatusCode.UNAUTHORIZED)
          );
      }

      const validatedData = ValidationUtils.getValidatedData(validation);

      // For regular users, they can only create notifications for themselves
      // For admin users, they can create notifications for any user
      const targetUserId =
        req.user?.role === 'ADMIN' && validatedData.user_id
          ? validatedData.user_id
          : userId;

      const notification = await NotificationService.createNotification({
        title: validatedData.title,
        message: validatedData.message,
        type: validatedData.type,
        link: validatedData.link,
        user_id: targetUserId,
        qrcode_id: validatedData.qrcode_id,
        scan_id: validatedData.scan_id,
        data: validatedData.data,
        sendPush: validatedData.sendPush,
      });

      return res
        .status(StatusCode.CREATED)
        .json(
          UniResponse.Success(
            'Notification created successfully',
            notification,
            StatusCode.CREATED
          )
        );
    }
  );

  // ======== TOGGLE PUSH NOTIFICATIONS ===============
  public static togglePushNotifications = asyncHandler(
    async (req: AuthenticatedRequest, res: Response) => {
      const userId = req.user?.userId;
      if (!userId) {
        return res
          .status(StatusCode.UNAUTHORIZED)
          .json(
            UniResponse.Error('User not authenticated', null, StatusCode.UNAUTHORIZED)
          );
      }

      const result = await NotificationService.togglePushNotifications(userId);

      return res
        .status(StatusCode.OK)
        .json(
          UniResponse.Success(
            `Push notifications ${result.pushNotificationsEnabled ? 'enabled' : 'disabled'} successfully`,
            result,
            StatusCode.OK
          )
        );
    }
  );

  // ======== GET PUSH NOTIFICATION STATUS ===============
  public static getPushNotificationStatus = asyncHandler(
    async (req: AuthenticatedRequest, res: Response) => {
      const userId = req.user?.userId;
      if (!userId) {
        return res
          .status(StatusCode.UNAUTHORIZED)
          .json(
            UniResponse.Error('User not authenticated', null, StatusCode.UNAUTHORIZED)
          );
      }

      const result = await NotificationService.getPushNotificationStatus(userId);

      return res
        .status(StatusCode.OK)
        .json(
          UniResponse.Success(
            'Push notification status retrieved successfully',
            result,
            StatusCode.OK
          )
        );
    }
  );
}
