import { CampaignStatus, DeliveryStatus } from "@prisma/client";

import { prisma } from "@/lib/prisma";

export const DEFAULT_MAX_SEND_ATTEMPTS = 3;

export const RETRY_BACKOFF_SECONDS = [10, 30, 120];

export function getRetryDelaySeconds(attempt: number) {
  if (attempt <= 1) {
    return RETRY_BACKOFF_SECONDS[0];
  }

  if (attempt - 1 < RETRY_BACKOFF_SECONDS.length) {
    return RETRY_BACKOFF_SECONDS[attempt - 1];
  }

  return RETRY_BACKOFF_SECONDS[RETRY_BACKOFF_SECONDS.length - 1];
}

export function renderCampaignMessage(templateBody: string, values: Record<string, string>) {
  return templateBody.replace(/\{\{\s*(\d+)\s*\}\}/g, (match, token) => {
    const key = String(token);
    return values[key] ?? match;
  });
}

export async function recalculateCampaignTotals(campaignId: string) {
  const recipients = await prisma.campaignRecipient.findMany({
    where: { campaignId },
    select: { sendStatus: true }
  });

  const totalRecipients = recipients.length;
  const totalSent = recipients.filter((recipient) => recipient.sendStatus !== DeliveryStatus.QUEUED).length;
  const totalDelivered = recipients.filter((recipient) =>
    recipient.sendStatus === DeliveryStatus.DELIVERED || recipient.sendStatus === DeliveryStatus.READ
  ).length;
  const totalRead = recipients.filter((recipient) => recipient.sendStatus === DeliveryStatus.READ).length;
  const totalFailed = recipients.filter((recipient) => recipient.sendStatus === DeliveryStatus.FAILED).length;
  const totalQueued = recipients.filter((recipient) => recipient.sendStatus === DeliveryStatus.QUEUED).length;

  const isDone = totalQueued === 0;
  const status = isDone
    ? totalFailed > 0
      ? totalSent > 0
        ? CampaignStatus.PARTIAL_FAILED
        : CampaignStatus.FAILED
      : CampaignStatus.COMPLETED
    : totalFailed > 0
      ? CampaignStatus.PARTIAL_FAILED
      : CampaignStatus.PROCESSING;

  const updateData: {
    totalRecipients: number;
    totalSent: number;
    totalDelivered: number;
    totalRead: number;
    totalFailed: number;
    status: CampaignStatus;
    finishedAt?: Date | null;
  } = {
    totalRecipients,
    totalSent,
    totalDelivered,
    totalRead,
    totalFailed,
    status
  };

  if (isDone) {
    updateData.finishedAt = new Date();
  }

  await prisma.broadcastCampaign.update({
    where: { id: campaignId },
    data: updateData
  });
}
