import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';

dayjs.extend(utc);
dayjs.extend(timezone);

import { Tasks } from '@/modules/tasks/tasks.model';
import { upsertTaskDailySummary } from '@/modules/tasks/dailySummary/dailySummary.service';
import { PipelineStage } from 'mongoose';
import { TaskDailySummary } from '@/modules/tasks/dailySummary/dailySummary.model';
import { createNotification } from '@/modules/notification/notification.service';
import {
  NotificationStatus,
  UserType,
} from '@/modules/notification/notification.constant';
import { getObjectId } from '@/shared/utils/commonHelper';
import { Status } from '@/shared/constants/enum.constant';
import { IUser } from '@/modules/user/user.interfaces';
import { TaskStatus } from '@/modules/tasks/tasks.constant';

const targetDate = dayjs().tz('Asia/Kolkata').format('YYYY-MM-DD');
export const runDailyTaskSummary = async () => {
  const pipeline: PipelineStage[] = [
    {
      $match: {
        status: { $in: ['pending', 'overdue'] },
        $expr: {
          $eq: [
            { $dateToString: { format: '%Y-%m-%d', date: '$activityDate' } },
            targetDate,
          ],
        },
      },
    },
    {
      $group: {
        _id: {
          userId: '$assignedTo',
          activityDate: {
            $dateToString: { format: '%Y-%m-%d', date: '$activityDate' },
          },
          activityType: '$activityType',
        },
        count: { $sum: 1 },
      },
    },
    {
      $group: {
        _id: {
          userId: '$_id.userId',
          activityDate: '$_id.activityDate',
        },
        activities: {
          $push: {
            k: '$_id.activityType',
            v: '$count',
          },
        },
      },
    },
    {
      $project: {
        userId: '$_id.userId',
        activityDate: '$_id.activityDate',
        activities: { $arrayToObject: '$activities' },
      },
    },
  ];

  const aggregates = await Tasks.aggregate(pipeline);

  // Upsert daily summaries for each user/date entry
  await Promise.all(
    aggregates.map((summary) =>
      upsertTaskDailySummary(
        summary.userId,
        new Date(summary.activityDate),
        summary.activities,
      ),
    ),
  );
};

export const sendDailyTaskSummaryNotification = async () => {
  const dailySummaries = await TaskDailySummary.find({
    activityDate: {
      $eq: new Date(targetDate),
    },
  })
    .populate({
      path: 'userId',
      select: 'firstName lastName',
      match: { status: Status.ACTIVE },
    })
    .lean();

  await Promise.all(
    dailySummaries.map(async (summary) => {
      const user = summary.userId as unknown as IUser;
      const description = [
        `Today you have ${summary.activities.call || 0} callbacks`,
        `${summary.activities.meeting || 0} meetings`,
        `and ${summary.activities.siteVisit || 0} site visits scheduled.`,
      ].join(' ');

      const userName = [user.firstName, user.lastName]
        .filter(Boolean)
        .join(' ');

      const appRedirect = {
        screenType: 'Daily_Task_Summary',
        id: summary.userId._id,
      };

      const isNotificationSent = await createNotification(
        {
          title: `Good Morning, ${userName} ☀️`,
          description,
          userType: UserType.SELF,
          user: getObjectId(summary.userId._id),
          status: NotificationStatus.SEND,
        },
        appRedirect,
      );

      if (isNotificationSent)
        await TaskDailySummary.findByIdAndDelete(summary._id);
    }),
  );
};

export const sendWeeklyTaskSummaryNotification = async () => {
  const weekStart = dayjs()
    .tz('Asia/Kolkata')
    .subtract(7, 'day')
    .format('YYYY-MM-DD');

  const pipeline: PipelineStage[] = [
    {
      $match: {
        status: TaskStatus.COMPLETED,
        assignedTo: { $exists: true },
        $expr: {
          $and: [
            {
              $gte: [
                { $dateToString: { format: '%Y-%m-%d', date: '$createdAt' } },
                weekStart,
              ],
            },
            {
              $lte: [
                { $dateToString: { format: '%Y-%m-%d', date: '$createdAt' } },
                targetDate,
              ],
            },
          ],
        },
      },
    },
    {
      $lookup: {
        from: 'users',
        localField: 'assignedTo',
        foreignField: '_id',
        as: 'user',
      },
    },
    { $unwind: '$user' },
    { $match: { 'user.status': Status.ACTIVE } },

    // Count tasks by user and activity type
    {
      $group: {
        _id: {
          userId: '$assignedTo',
          activityType: '$activityType',
        },
        count: { $sum: 1 },
      },
    },
    {
      $group: {
        _id: '$_id.userId',
        activities: {
          $push: {
            k: '$_id.activityType',
            v: '$count',
          },
        },
      },
    },
    {
      $project: {
        _id: 0,
        userId: '$_id',
        activities: { $arrayToObject: '$activities' },
      },
    },

    // Lookup converted leads in the same period per user
    {
      $lookup: {
        from: 'leads',
        let: { userId: '$userId' },
        pipeline: [
          {
            $match: {
              $expr: {
                $and: [
                  { $eq: ['$assignedTo', '$$userId'] },
                  { $eq: ['$isConvertedToCustomer', true] },
                  {
                    $gte: [
                      {
                        $dateToString: {
                          format: '%Y-%m-%d',
                          date: '$updatedAt',
                        },
                      },
                      weekStart,
                    ],
                  },
                  {
                    $lte: [
                      {
                        $dateToString: {
                          format: '%Y-%m-%d',
                          date: '$updatedAt',
                        },
                      },
                      targetDate,
                    ],
                  },
                ],
              },
            },
          },
          { $count: 'leadsConverted' },
        ],
        as: 'leadSummary',
      },
    },
    {
      $addFields: {
        leadsConverted: {
          $ifNull: [{ $arrayElemAt: ['$leadSummary.leadsConverted', 0] }, 0],
        },
      },
    },
    {
      $project: {
        leadSummary: 0,
      },
    },
  ];

  const aggregates = await Tasks.aggregate(pipeline);

  // Send notification for each user's weekly summary
  await Promise.all(
    aggregates.map(async (summary) => {
      const meetingsDone = summary.activities.meeting || 0;
      const siteVisitsDone = summary.activities.siteVisit || 0;

      const description = `Your performance last week: ${summary.leadsConverted || 0} leads converted, ${meetingsDone || 0} meetings, ${siteVisitsDone || 0} site visits.`;

      await createNotification(
        {
          title: 'Weekly Performance Summary',
          description,
          userType: UserType.SELF,
          user: getObjectId(summary.userId),
          status: NotificationStatus.SEND,
        },
        { screenType: 'Weekly_Task_Summary', id: summary.userId },
      );
    }),
  );
};
