import { PushNotification } from './pushNotification.model';
import {
  NewCreatedPushNotification,
  IPushNotification,
  IPushNotificationDoc,
  UpdatePushNotificationBody,
} from './pushNotification.interface';
import { ApiError } from '@/shared/utils/errors';
import responseCodes from '@/shared/utils/responseCode/responseCode';
import { FilterQuery } from 'mongoose';
import { PaginateOptions } from '@/shared/utils/plugins/paginate/paginate';
import { getObjectId } from '@/shared/utils/commonHelper';

const { NotificationResponseCodes } = responseCodes;

/**
 * Create a new push notification.
 * Can be used from any internal service.
 */
export const createPushNotification = async (
  payload: NewCreatedPushNotification,
): Promise<IPushNotificationDoc> => {
  const notification = await PushNotification.create(payload);

  if (!notification)
    throw new ApiError(
      500,
      'Failed to create push notification',
      true,
      '',
      NotificationResponseCodes.NOTIFICATION_ERROR,
    );

  return notification;
};

/**
 * Query push notifications by filters.
 * Especially useful to fetch notifications for a user (`receivedTo`).
 */
export const queryPushNotifications = async (
  rawFilter: Record<string, unknown>,
  options: PaginateOptions,
  loggedInUserId: string,
) => {
  const { search, ...rest } = rawFilter;
  const filter: FilterQuery<IPushNotification> = {
    ...rest,
    createdBy: {
      $ne: getObjectId(loggedInUserId),
    },
  };

  if (typeof search === 'string' && search.trim())
    filter.$or = [
      { title: { $regex: search, $options: 'i' } },
      { description: { $regex: search, $options: 'i' } },
    ];

  return PushNotification.paginate(filter, options);
};

export const updatePushNotification = async (
  id: string,
  updateData: UpdatePushNotificationBody,
): Promise<void> => {
  const result = await PushNotification.updateOne(
    { _id: getObjectId(id) },
    { $set: updateData },
  );

  if (result.matchedCount === 0)
    throw new ApiError(
      404,
      'Push notification not found',
      false,
      '',
      NotificationResponseCodes.NOTIFICATION_NOT_FOUND,
    );
};

export const bulkUpdatePushNotificationsByIds = async (
  userId: string,
  updateData: UpdatePushNotificationBody,
): Promise<void> => {
  const result = await PushNotification.updateMany(
    {
      receivedTo: getObjectId(userId) },
    { $set: { read: updateData.read } },
  );

  if (result.matchedCount === 0)
    throw new ApiError(
      404,
      'Push notifications not found',
      false,
      '',
      NotificationResponseCodes.NOTIFICATION_NOT_FOUND,
    );
};
