// utils/activityReminderService.ts

import { Types } from 'mongoose';

import { ActivityRemainder } from '@/modules/activity/activityRemainder/activityRemainder.model';
import {
  NotificationDevice,
  NotificationStatus,
  NotificationType,
  UserType,
} from '@/modules/notification/notification.constant';
import { createNotification } from '@/modules/notification/notification.service';
import { getObjectId } from '@/shared/utils/commonHelper';
import { PopulatedActivityRemainderFields } from '@/modules/activity/activityRemainder/activityRemainder.interface';

function getDisplayActivityType(
  title?: string | null,
  fallback?: string | null,
): string {
  const raw = title ?? fallback ?? 'activity';
  const lower = String(raw).toLowerCase().trim();
  const scheduleMatch = lower.match(/schedule\s*[-–]\s*(.+)/);
  const part = scheduleMatch ? scheduleMatch[1].trim() : lower;
  if (part.includes('call')) return 'Call';
  if (part.includes('meeting')) return 'Meeting';
  if (part.includes('site') && part.includes('visit')) return 'Site Visit';
  if (part === 'site-visit' || part === 'sitevisit') return 'Site Visit';
  if (part === 'call') return 'Call';
  if (part === 'meeting') return 'Meeting';
  return part.charAt(0).toUpperCase() + part.slice(1).replace(/-/g, ' ') || 'Activity';
}

export const sendActivityReminderNotification = async ({
  activityRemainderId,
  appRedirect,
}): Promise<boolean> => {
  const remainder = await ActivityRemainder.findById(activityRemainderId)
    .populate([
      {
        path: 'leadId',
        select: 'contactDetails',
      },
      {
        path: 'contactId',
        select: 'firstName lastName',
      },
      {
        path: 'activityId',
        select: 'status title',
      },
    ])

    .lean<PopulatedActivityRemainderFields>();

  if (!remainder || !remainder.activityId) return false;

  if (remainder?.status === 'completed') {
    await ActivityRemainder.findByIdAndDelete(activityRemainderId);
    console.log(
      `Deleted completed activity remainder ID: ${activityRemainderId}`,
    );
    return false; // Return false as no notification was sent
  }

  if (remainder.isNotificationSent === true) {
    console.log(
      `Notification already sent for remainder ID: ${activityRemainderId}. Skipping.`,
    );
    return true;
  }

  const now = new Date();

  const scheduledTime = new Date(remainder.scheduleDateTime as Date);

  const timeDiffMinutes =
    (now.getTime() - scheduledTime.getTime()) / (1000 * 60);

  const leadName = remainder.leadId?.contactDetails?.name || 'Lead';
  const activityRef = remainder.activityId as { title?: string } | null;
  const activityType = getDisplayActivityType(activityRef?.title);
  const timeStr = scheduledTime.toLocaleTimeString('en-US', {
    timeZone: 'Asia/Kolkata',
    hour: 'numeric',
    minute: '2-digit',
    hour12: true,
  });

  let title: string;
  let description: string;
  const users: Types.ObjectId[] = [getObjectId(remainder.assignedTo)]; // Activity owner

  // Overdue: also send to createdBy/manager
  if (timeDiffMinutes > 15)
    if (remainder.createdBy) users.push(getObjectId(remainder.createdBy));

  if (timeDiffMinutes > 15) {
    // OVERDUE (>15 min after due)
    title = `Overdue ${activityType}`;
    description = `Your ${activityType.toLowerCase()} for ${leadName} was scheduled at ${timeStr}. Please update the status.`;
  } else if (timeDiffMinutes >= 0) {
    // DUE NOW (0 to 15 min after due)
    title = `${activityType} Due Now`;
    description = `Your ${activityType.toLowerCase()} for ${leadName} is due now.`;
  } else if (timeDiffMinutes >= -30 && timeDiffMinutes < 0) {
    // T-30 (30 min before due)
    title = `Upcoming ${activityType} at ${timeStr}`;
    description = `Your ${activityType.toLowerCase()} with ${leadName} starts in ${Math.round(Math.abs(timeDiffMinutes))} minutes.`;
  } else {
    return; // Not in any notification window
  }

  // Send to multiple users (assignedTo + optionally createdBy)
  const isNotificationSent = await createNotification(
    {
      title,
      description,
      userType: UserType.SELF,
      users: users,
      device: NotificationDevice.ALL,
      status: NotificationStatus.SEND,
      notificationType: NotificationType.ALERT,
    },
    appRedirect,
  );

  if (isNotificationSent)
    await ActivityRemainder.findByIdAndUpdate(
      activityRemainderId,
      { $set: { isNotificationSent: true } },
      { new: true },
    );

  return isNotificationSent;
};

export const checkAndSendActivityReminders = async () => {
  const now = new Date();
  const thirtyMinsAgo = new Date(now.getTime() - 30 * 60 * 1000);

  const fifteenMinsLater = new Date(now.getTime() + 15 * 60 * 1000);

  const reminders = await ActivityRemainder.find({
    scheduleDateTime: {
      $gte: thirtyMinsAgo,
      $lte: fifteenMinsLater,
    },
  }).lean();

  await Promise.allSettled(
    reminders.map((remainder) =>
      sendActivityReminderNotification({
        activityRemainderId: remainder._id.toString(),
        appRedirect: {
          screenType: 'Lead_Details',
          id: remainder.leadId?.toString(),
        },
      }),
    ),
  );
};
