import {
  buildAlertMailContent,
  getAlertMailPreview,
  type AlertMailGroup,
} from "@/services/alertes-mail.service";
import {
  claimAlertMailOccurrences,
  markAlertMailClaimsFailed,
  markAlertMailClaimsSent,
} from "@/services/alertes-mail-history.service";

type MailSender = (mail: {
  recipients: string[];
  subject: string;
  html: string;
}) => Promise<{
  messageId?: string | null;
}>;

export async function dispatchAlertMailOnce(options: {
  group: AlertMailGroup;
  send: MailSender;
}) {
  const preview = await getAlertMailPreview(options.group);

  if (preview.recipients.length === 0) {
    return { status: "SKIPPED" as const, reason: "NO_RECIPIENT", sentCount: 0 };
  }

  const items = preview.sections.flatMap((section) => section.messages);
  const claims = await claimAlertMailOccurrences(
    options.group,
    items.map((item) => item.occurrenceKey),
  );
  const claimedKeys = new Set(claims.map((claim) => claim.occurrenceKey));
  const sections = preview.sections
    .map((section) => ({
      ...section,
      messages: section.messages.filter((item) =>
        claimedKeys.has(item.occurrenceKey),
      ),
    }))
    .filter((section) => section.messages.length > 0);

  if (sections.length === 0) {
    return { status: "SKIPPED" as const, reason: "ALREADY_SENT", sentCount: 0 };
  }

  try {
    const result = await options.send({
      recipients: preview.recipients,
      subject: preview.subject,
      html: buildAlertMailContent(
        preview.subject,
        preview.groupLabel,
        sections,
      ),
    });

    await markAlertMailClaimsSent(claims, {
      recipients: preview.recipients,
      messageId: result.messageId,
    });

    return {
      status: "SENT" as const,
      sentCount: claims.length,
      messageId: result.messageId ?? null,
    };
  } catch (error) {
    await markAlertMailClaimsFailed(claims, error);
    throw error;
  }
}

