import { Order } from "@/models/Order";
import { Client } from "@/models/Client";
import { DiscountCode } from "@/models/DiscountCode";
import { getSettings } from "@/lib/settings";
import { randomRewardCode } from "@/lib/rewardCode";
import { notifyRecipient } from "@/lib/notifications";
import { sendMailIfEnabled } from "@/lib/mail";
import { emailShell } from "@/lib/emailTemplate";

// Wird genau einmal pro Auftrag aufgerufen, in dem Moment, in dem er von
// unbezahlt auf bezahlt wechselt (siehe markOrderPaidAction und der
// Stripe-Webhook, beide atomar gegen Doppelverarbeitung abgesichert) — zählt
// danach die bezahlten Aufträge des Kunden und vergibt bei jedem
// ordersThreshold-ten eine neue Prämie. Fehler hier dürfen die eigentliche
// Zahlungsverbuchung nicht verhindern, daher komplett separat abgesichert.
export async function checkAndGrantLoyaltyReward(clientId: string): Promise<void> {
  try {
    const settings = await getSettings();
    if (!settings.loyaltySettings?.enabled) return;
    const threshold = settings.loyaltySettings.ordersThreshold;
    if (!threshold || threshold < 1) return;

    // rejected: {$ne: true} statt rejected:false — deckt auch ältere
    // Dokumente ohne das Feld ab (Mongo-Äquivalent zum "!o.rejected"-Muster
    // aus statistics/page.tsx). Ein bezahlter, aber nachträglich abgelehnter/
    // stornierter Auftrag (z. B. Rückerstattung nach Absage) soll nicht auf
    // die Schwelle zählen.
    const paidCount = await Order.countDocuments({ clientId, paid: true, rejected: { $ne: true } });
    if (paidCount === 0 || paidCount % threshold !== 0) return;

    const client = await Client.findById(clientId).select("email name firstName nickname locale").lean();
    if (!client) return;

    let code = randomRewardCode();
    while (await DiscountCode.findOne({ code })) code = randomRewardCode();

    await DiscountCode.create({
      code,
      type: settings.loyaltySettings.rewardType,
      value: settings.loyaltySettings.rewardValue,
      maxUses: 1,
      ownerId: clientId,
      active: true,
      note: `Stammkunden-Prämie — ${paidCount}. bezahlter Auftrag.`,
    });

    const name = client.nickname || client.firstName || client.name;
    const isEn = client.locale === "en";
    const html = await emailShell({
      heading: `Hi ${name},`,
      bodyHtml: isEn
        ? `<p style="margin:0 0 8px;">This was already your <strong>${paidCount}.</strong> booking with us — thank you for coming back! As a little thank-you, here's a discount code for your next shoot:</p>
           <p style="margin:12px 0; font-size:1.2rem; letter-spacing:0.05em;"><strong>${code}</strong></p>`
        : `<p style="margin:0 0 8px;">Das war schon dein <strong>${paidCount}.</strong> Auftrag bei uns — danke, dass du wiederkommst! Als kleines Dankeschön hier ein Rabattcode für dein nächstes Shooting:</p>
           <p style="margin:12px 0; font-size:1.2rem; letter-spacing:0.05em;"><strong>${code}</strong></p>`,
      buttonLabel: isEn ? "Book a new shoot" : "Neues Shooting anfragen",
      buttonUrl: `${process.env.SITE_URL}/${client.locale}/angebote`,
      footerNote: isEn ? "Thank you for being a loyal customer!" : "Danke, dass du uns treu bleibst!",
    });
    await sendMailIfEnabled(clientId, client.email, isEn ? "Thank you for coming back!" : "Danke, dass du wiederkommst!", html);
    await notifyRecipient(clientId, {
      type: "loyalty_reward",
      title: isEn ? "A little thank-you for you" : "Ein kleines Dankeschön für dich",
      body: isEn ? `Discount code: ${code}` : `Rabattcode: ${code}`,
      link: `/${client.locale}/account`,
    });
  } catch (err) {
    console.error("Stammkunden-Prämie fehlgeschlagen:", err);
  }
}
