import dayjs from "dayjs";
import { MessageRecord } from "../../src/models/messageRecordModel";
import { MessageStatsDailyUid } from "../../src/models/messageStatsDailyUidModel";

const TIMEZONE = "America/Los_Angeles";
const BATCH_SIZE = 2000;

async function run(dateStr?: string | dayjs.Dayjs): Promise<string> {
  const targetDay = dateStr ? dayjs(dateStr).startOf("day") : dayjs().subtract(1, "day").startOf("day");
  if (!targetDay.isValid()) {
    throw new Error(`Invalid date: ${dateStr}`);
  }

  const dateKey = targetDay.format("YYYY-MM-DD");
  const start = targetDay.toDate();
  const end = targetDay.add(1, "day").startOf("day").toDate();

  const startedAt = Date.now();
  console.log(`[MessageStatsPreAgg Cron] start date=${dateKey}`);

  const pipeline = [
    { $match: { createdAt: { $gte: start, $lt: end } } },
    {
      $group: {
        _id: {
          date: { $dateTrunc: { date: "$createdAt", unit: "day", timezone: TIMEZONE } },
          dateKey: { $dateToString: { format: "%Y-%m-%d", date: "$createdAt", timezone: TIMEZONE } },
          strategyId: "$strategyId",
          strategyName: "$strategyName",
          templateName: "$templateName",
          cc: "$cc",
          image: "$image",
          status: "$status",
          inforeground: "$inforeground",
          uid: "$uid",
        },
        msgCount: { $sum: 1 },
      },
    },
  ];

  const cursor = MessageRecord.aggregate(pipeline).allowDiskUse(true).cursor({ batchSize: BATCH_SIZE });

  let processed = 0;
  let ops: any[] = [];

  for await (const row of cursor) {
    const id = row._id || {};
    ops.push({
      updateOne: {
        filter: {
          dateKey: id.dateKey,
          strategyId: id.strategyId || null,
          strategyName: id.strategyName || null,
          templateName: id.templateName || null,
          cc: id.cc || null,
          image: id.image || null,
          status: id.status,
          inforeground: id.inforeground,
          uid: id.uid,
        },
        update: {
          $set: {
            date: id.date,
            dateKey: id.dateKey,
            strategyId: id.strategyId || null,
            strategyName: id.strategyName || null,
            templateName: id.templateName || null,
            cc: id.cc || null,
            image: id.image || null,
            status: id.status,
            inforeground: id.inforeground,
            uid: id.uid,
            msgCount: row.msgCount,
          },
        },
        upsert: true,
      },
    });

    if (ops.length >= BATCH_SIZE) {
      await MessageStatsDailyUid.bulkWrite(ops, { ordered: false });
      processed += ops.length;
      ops = [];
    }
  }

  if (ops.length > 0) {
    await MessageStatsDailyUid.bulkWrite(ops, { ordered: false });
    processed += ops.length;
  }

  const summary = `[MessageStatsPreAgg Cron] done date=${dateKey} upsert=${processed} elapsed=${Date.now() - startedAt}ms`;
  console.log(summary);
  return summary;
}

export = { run };
