import { connectDB } from "@/lib/db";
import { Client } from "@/models/Client";
import { Order } from "@/models/Order";
import { ClientPhotoFolder } from "@/models/ClientPhotoFolder";
import { PhotoRating } from "@/models/PhotoRating";
import { sendMailIfEnabled } from "@/lib/mail";
import { emailShell } from "@/lib/emailTemplate";

async function safeSend(fn: () => Promise<void>) {
  try {
    await fn();
  } catch (err) {
    console.error("Jahresrückblick-Mail fehlgeschlagen:", err);
  }
}

function sendYearlyRecapMail(
  client: { id: string; email: string; name: string; locale: "de" | "en" },
  year: number,
  stats: { shoots: number; approvedPhotos: number }
) {
  return safeSend(async () => {
    const isEn = client.locale === "en";
    const bodyHtml = isEn
      ? `<p style="margin:0;">What a year! Together we had <strong>${stats.shoots}</strong> shoot${stats.shoots === 1 ? "" : "s"}${
          stats.approvedPhotos > 0 ? ` and ${stats.approvedPhotos} photo${stats.approvedPhotos === 1 ? "" : "s"} delivered` : ""
        } in ${year}. Thank you so much for trusting me with your ideas — I'd love to shoot with you again.</p>`
      : `<p style="margin:0;">Was für ein Jahr! Zusammen hatten wir <strong>${stats.shoots}</strong> Shooting${stats.shoots === 1 ? "" : "s"}${
          stats.approvedPhotos > 0 ? ` und ${stats.approvedPhotos} freigegebene${stats.approvedPhotos === 1 ? "s" : ""} Foto${stats.approvedPhotos === 1 ? "" : "s"}` : ""
        } in ${year}. Danke, dass du mir deine Ideen anvertraut hast — ich würde mich riesig freuen, dich wieder vor der Kamera zu haben.</p>`;
    const html = await emailShell({
      heading: isEn ? `Your ${year} in review, ${client.name}` : `Dein Jahr ${year} im Rückblick, ${client.name}`,
      bodyHtml,
      buttonLabel: isEn ? "Book another shoot" : "Nächstes Shooting buchen",
      buttonUrl: `${process.env.SITE_URL}/${client.locale}/angebote`,
      footerNote: isEn
        ? "Sent once a year, in December, to clients who had at least one shoot that year."
        : "Wird einmal im Jahr im Dezember an Kund:innen mit mindestens einem Shooting in diesem Jahr verschickt.",
    });
    await sendMailIfEnabled(
      client.id,
      client.email,
      isEn ? `Your ${year} in review — Rakku Photography` : `Dein Jahr ${year} im Rückblick — Rakku Photography`,
      html
    );
  });
}

// Läuft täglich (siehe api/cron/yearly-recap), wird aber nur im Dezember
// tatsächlich aktiv — ein Jahresrückblick vor Jahresende ergibt inhaltlich
// keinen Sinn (das Jahr ist ja noch nicht rum). lastYearlyRecapSentYear auf
// Client verhindert Doppelversand bei mehreren Cron-Läufen im selben Monat.
export async function runYearlyRecapSweep() {
  await connectDB();
  const now = new Date();
  if (now.getMonth() !== 11) return { sent: 0, skipped: "not_december" as const };

  const year = now.getFullYear();
  const yearStart = new Date(Date.UTC(year, 0, 1));
  const yearEnd = new Date(Date.UTC(year + 1, 0, 1));

  const candidates = await Order.aggregate<{ _id: string; shoots: number }>([
    { $match: { rejected: false, shootDate: { $gte: yearStart, $lt: yearEnd } } },
    { $group: { _id: "$clientId", shoots: { $sum: 1 } } },
  ]);

  let sent = 0;
  for (const candidate of candidates) {
    const client = await Client.findById(candidate._id)
      .select("email name firstName nickname locale role lastYearlyRecapSentYear")
      .lean();
    if (!client || client.role !== "client") continue;
    if (client.lastYearlyRecapSentYear === year) continue;

    const folders = await ClientPhotoFolder.find({ clientId: candidate._id, createdAt: { $gte: yearStart, $lt: yearEnd } })
      .select("_id")
      .lean();
    const approvedPhotos = folders.length
      ? await PhotoRating.countDocuments({ folderId: { $in: folders.map((f) => f._id) }, approvedForDownload: true })
      : 0;

    await sendYearlyRecapMail(
      {
        id: String(candidate._id),
        email: client.email,
        name: client.nickname || client.firstName || client.name,
        locale: client.locale,
      },
      year,
      { shoots: candidate.shoots, approvedPhotos }
    );
    await Client.findByIdAndUpdate(candidate._id, { lastYearlyRecapSentYear: year });
    sent += 1;
  }

  return { sent, candidates: candidates.length };
}
