import { NextRequest, NextResponse } from "next/server";
import crypto from "node:crypto";
import { db, cookingHistory, eq, and, isNotNull, isNull } from "@epicure/db";
import { sendEmail, notificationEmailHtml } from "@/lib/email";
import { sendPushNotification } from "@/lib/push";
import { isLeftoverExpiringSoon } from "@/lib/leftover-match";
import { getMessages, formatMessage } from "@/lib/i18n/server";
import { isNotificationCategoryEnabled } from "@/lib/notification-prefs";

// Internal cron endpoint — triggered daily by a cron container (see
// compose.prod.yml / cron/crontab). Not part of the public API surface;
// protected by a shared secret rather than user auth.
//
// For every cooking_history row tied to a batch-cook dish, checks whether it
// expires soon (see lib/leftover-match.ts) and hasn't already been reminded
// about, then sends one push + email and marks it reminded so it never fires
// twice for the same cooked dish.

function isAuthorized(req: NextRequest): boolean {
  const secret = process.env["CRON_SECRET"];
  if (!secret) return false;

  const header = req.headers.get("authorization");
  if (!header?.startsWith("Bearer ")) return false;
  const provided = header.slice("Bearer ".length);

  const a = Buffer.from(provided);
  const b = Buffer.from(secret);
  if (a.length !== b.length) return false;
  return crypto.timingSafeEqual(a, b);
}

export async function POST(req: NextRequest) {
  if (!isAuthorized(req)) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  const candidates = await db.query.cookingHistory.findMany({
    where: and(isNotNull(cookingHistory.batchDishId), isNull(cookingHistory.expiryReminderSentAt)),
    with: {
      batchDish: { columns: { id: true, name: true, fridgeDays: true } },
      recipe: { columns: { id: true, title: true } },
      user: { columns: { id: true, email: true, locale: true } },
    },
  });

  let sent = 0;
  for (const log of candidates) {
    if (!log.batchDish || !log.user) continue;
    if (!isLeftoverExpiringSoon(log.cookedAt, log.batchDish.fridgeDays)) continue;

    const messages = getMessages(log.user.locale);
    const template = messages.notifications.detail.leftoverExpiring;
    const title = messages.notifications.pushTitle.leftoverExpiring;
    const body = formatMessage(template, { dish: log.batchDish.name, title: log.recipe.title });
    const url = `/recipes/${log.recipe.id}`;
    const pushEnabled = await isNotificationCategoryEnabled(log.user.id, "leftoverExpiring");

    await Promise.all([
      pushEnabled
        ? sendPushNotification(log.user.id, { title, body, url }).catch((err) => {
            console.error("[leftover-reminders] push failed", err);
          })
        : Promise.resolve(),
      log.user.email
        ? sendEmail({
            to: log.user.email,
            subject: title,
            html: notificationEmailHtml(title, body, `${process.env["BETTER_AUTH_URL"] ?? "http://localhost:3000"}${url}`),
          }).catch((err) => {
            console.error("[leftover-reminders] email failed", err);
          })
        : Promise.resolve(),
    ]);

    await db.update(cookingHistory)
      .set({ expiryReminderSentAt: new Date() })
      .where(eq(cookingHistory.id, log.id));
    sent++;
  }

  return NextResponse.json({ ok: true, checked: candidates.length, sent });
}
