import { Types } from 'mongoose';

import { updateLeadScoreFromActivity } from '../leadScore/leadScore.service';
import { ITasksBase, PopulatedTask } from './tasks.interface';
import { Tasks } from './tasks.model';
import { TemplateName } from '@/shared/constants';
import moment from 'moment';
import config from '@/shared/config/config';
import { sendEmailWithActiveTemplate } from '../communication/email/email.helper';
import { TriggerPoint } from '@/shared/constants/enum.constant';
import { getDateString, getTimeString } from '@/shared/utils/date';
import { sendWhatsappMessage } from '@/shared/communicationAlerts/sendMetaMsg';
import { getDialCodePhone, getFullName } from '@/shared/utils/commonHelper';
import { TaskActivityType } from './tasks.constant';
import { sendFast2smsMessage } from '@/shared/communicationAlerts/sendFast2smsMsg';

export const handleLeadUpdateFromTask = async (
  task: ITasksBase,
): Promise<void> => {
  if (!task?.leadId || task.status !== 'pending') return;

  const { activityType } = task;

  const validTypes = ['meeting', 'siteVisit'];
  if (!validTypes.includes(activityType)) return;

  const leadId = task.leadId.toString();

  const existingTasks = await Tasks.find({
    leadId,
    activityType,
    status: 'pending',
    _id: { $ne: task._id },
  });

  const count = existingTasks.length;

  if (count === 0) {
    const activity =
      activityType === 'meeting'
        ? 'meeting_scheduled_first'
        : 'site_visit_scheduled_first';
    await updateLeadScoreFromActivity(activity, leadId);
  } else if (count === 1) {
    const activity =
      activityType === 'meeting'
        ? 'meeting_scheduled_second'
        : 'site_visit_scheduled_second';
    await updateLeadScoreFromActivity(activity, leadId);
  } else {
    console.log(
      `Skipping ${activityType} lead update — already has 2+ pending tasks`,
    );
  }
};

export const handleTaskCompletionUpdate = async (
  task: ITasksBase,
): Promise<void> => {
  if (!task?.leadId || task.status !== 'completed') return;

  const { activityType } = task;

  const validTypes = ['meeting', 'siteVisit'];
  if (!validTypes.includes(activityType)) return;

  const leadId = task.leadId.toString();

  const completedTasks = await Tasks.find({
    leadId,
    activityType,
    status: 'completed',
    _id: { $ne: task._id },
  });

  const count = completedTasks.length;

  if (count === 0) {
    const activity =
      activityType === 'meeting'
        ? 'meeting_successful_first'
        : 'site_visit_successful_first';
    await updateLeadScoreFromActivity(activity, leadId);
  } else if (count === 1) {
    const activity =
      activityType === 'meeting'
        ? 'meeting_successful_second'
        : 'site_visit_successful_second';
    await updateLeadScoreFromActivity(activity, leadId);
  } else {
    console.log(
      `Skipping ${activityType} completion score — already has 2+ completed tasks`,
    );
  }
};

export const sendMail = async (taskId: Types.ObjectId) => {
  const task = await Tasks.findById(taskId)
    .populate([
      { path: 'contactId', select: 'firstName lastName email phone' },
      {
        path: 'leadId',
        select: 'contact',
        populate: {
          path: 'contact',
          select: 'firstName lastName email phone',
        },
      },
      { path: 'createdBy', select: 'firstName lastName email profileImage' },
      { path: 'assignedTo', select: 'firstName lastName email profileImage' },
      { path: 'companyId', select: 'name' },
    ])
    .lean<PopulatedTask>();

  if (!task) return;

  // ✅ Choose between contact or lead
  const person = task.contactId || task.leadId?.contact;
  const personName = person
    ? `${person.firstName ?? ''} ${person.lastName ?? ''}`.trim()
    : 'N/A';
  const personContact =
    person?.phone?.length > 0
      ? `+${person.phone[0].countryCode} ${person.phone[0].number}`
      : 'N/A';

  await sendEmailWithActiveTemplate({
    to: task.assignedTo.email,
    companyId: task.companyId?._id,
    scenario: TemplateName.TasksAssigned,
    templateParams: {
      fullName: `${task.assignedTo.firstName} ${task.assignedTo.lastName}`,
      companyName: task.companyId?.name ?? 'N/A',
      leadName: personName,
      contact: personContact,
      task: task.activityType,
      dueDate: moment(task.activityDate).format('dddd DD MMM YYYY, hh:mm A'),
      assignedBy: `${task.createdBy.firstName} ${task.createdBy.lastName}`,
      taskUrl: `${config.clientUrl}/tasks`,
    },
  });
};

export const getPopulatedTask = async ({ taskId }) => {
  const populatedTask = await Tasks.findById(taskId)
    .populate([
      { path: 'contactId', select: 'firstName lastName email phone' },
      {
        path: 'leadId',
        select: 'contact',
        populate: {
          path: 'contact',
          select: 'firstName lastName email phone',
        },
      },
      { path: 'createdBy', select: 'firstName lastName email profileImage' },
      {
        path: 'assignedTo',
        select: 'firstName lastName email profileImage phone',
      },
      { path: 'companyId', select: 'name' },
      { path: 'project', select: 'projectName' },
    ])
    .lean<PopulatedTask>();

  return populatedTask;
};

export const sendMeetingWhatsApp = async ({
  data,
  taskId,
  triggerPoint,
  assignDate = false,
  activityType,
}) => {
  const result = await getPopulatedTask({ taskId });
  const contactOrLeadFirstName =
    result.contactId?.firstName ?? result.leadId?.contact?.firstName ?? 'N/A';

  const companyName = result.companyId?.name ?? 'N/A';
  const meetingDate = getDateString(result.activityDate);
  const meetingTime = getTimeString(result.activityDate);
  const assignedToName = getFullName(result.assignedTo);
  const assignedToPhone = getDialCodePhone(result.assignedTo?.phone);
  const organizer = companyName;

  let whatsappVariables;
  let smsVariables;

  if (activityType === TaskActivityType.SITE_VISIT && result.project) {
    const combinedDateTime = `${meetingDate} at ${meetingTime}`;
    const projectName = result.project.projectName ?? 'N/A';

    whatsappVariables = [
      contactOrLeadFirstName,
      projectName,
      combinedDateTime,
      assignedToName,
      assignedToPhone,
      organizer,
    ];

    smsVariables = [
      contactOrLeadFirstName,
      `${organizer} on ${combinedDateTime}`,
      `${assignedToName} on ${assignedToPhone}`,
    ];
  } else {
    // Default payload for other activity types
    whatsappVariables = [
      contactOrLeadFirstName,
      companyName,
      meetingDate,
      assignedToName,
      assignedToPhone,
      organizer,
    ];

    smsVariables = [
      contactOrLeadFirstName,
      `${organizer} on ${meetingDate}`,
      `${assignedToName} on ${assignedToPhone}`,
    ];

    if (assignDate) {
      // Insert meetingTime at index 3 if not already there
      if (!whatsappVariables.includes(meetingTime))
        whatsappVariables.splice(3, 0, meetingTime);
    } else {
      whatsappVariables = whatsappVariables.filter(
        (item) => item !== meetingTime,
      );
    }
  }

  let toNumber = null;
  if (data.contactId && result.contactId?.phone?.[0])
    toNumber =
      String(result.contactId.phone[0]?.countryCode || '') +
      String(result.contactId.phone[0]?.number || '');
  else if (data.leadId && result.leadId?.contact?.phone?.[0])
    toNumber =
      String(result.leadId?.contact?.phone[0]?.countryCode || '') +
      String(result.leadId?.contact?.phone[0]?.number || '');

  if (toNumber && data.activityType === activityType) {
    await sendWhatsappMessage({
      companyId: data.companyId,
      triggerPoint: TriggerPoint[triggerPoint],
      toNumber,
      variables: whatsappVariables,
      isNamedParams: false,
    });

    await sendFast2smsMessage(
      data.companyId,
      TriggerPoint[triggerPoint],
      String(toNumber),
      smsVariables,
    );
  }
};
