import { createNotificationsForUsers } from "./create-notification.js";

type DbClient = {
  estimate: {
    findMany: (args: {
      where: {
        versions: {
          some: {
            status: string;
            submittedAt: { lte: Date };
          };
        };
      };
      select: {
        id: true;
        name: true;
        projectId: true;
        versions: {
          where: { status: string };
          select: { id: true; versionNumber: true; submittedAt: true };
          orderBy: { versionNumber: "desc" };
          take: 1;
        };
      };
    }) => Promise<
      Array<{
        id: string;
        name: string;
        projectId: string | null;
        versions: Array<{
          id: string;
          versionNumber: number;
          submittedAt: Date | null;
        }>;
      }>
    >;
  };
  notification: {
    findFirst: (args: {
      where: {
        entityId: string;
        entityType: string;
        type: string;
      };
      select: { id: true };
    }) => Promise<{ id: string } | null>;
    create: (args: {
      data: {
        userId: string;
        type: string;
        category: string;
        priority: string;
        title: string;
        body: string;
        entityId: string;
        entityType: string;
        link: string;
        channel: string;
      };
    }) => Promise<{ id: string; userId: string }>;
  };
  user: {
    findMany: (args: {
      where: { systemRole: { in: string[] } };
      select: { id: true };
    }) => Promise<Array<{ id: string }>>;
  };
};

const REMINDER_DAYS = 3;

/**
 * Find all estimates that have a version in SUBMITTED status for longer than
 * REMINDER_DAYS days and create a single reminder notification per estimate
 * for all managers/admins.
 *
 * Returns the number of new reminders created.
 */
export async function checkPendingEstimateReminders(
  db: DbClient,
): Promise<number> {
  const cutoff = new Date();
  cutoff.setDate(cutoff.getDate() - REMINDER_DAYS);

  const pendingEstimates = await db.estimate.findMany({
    where: {
      versions: {
        some: {
          status: "SUBMITTED",
          submittedAt: { lte: cutoff },
        },
      },
    },
    select: {
      id: true,
      name: true,
      projectId: true,
      versions: {
        where: { status: "SUBMITTED" },
        select: { id: true, versionNumber: true, submittedAt: true },
        orderBy: { versionNumber: "desc" },
        take: 1,
      },
    },
  });

  if (pendingEstimates.length === 0) return 0;

  const managers = await db.user.findMany({
    where: { systemRole: { in: ["ADMIN", "MANAGER"] } },
    select: { id: true },
  });

  if (managers.length === 0) return 0;

  let reminderCount = 0;

  for (const estimate of pendingEstimates) {
    const version = estimate.versions[0];
    if (!version) continue;

    // Check if we already sent a reminder for this version
    const existing = await db.notification.findFirst({
      where: {
        entityId: version.id,
        entityType: "estimate_approval_reminder",
        type: "ESTIMATE_APPROVAL_REMINDER",
      },
      select: { id: true },
    });

    if (existing) continue;

    const daysPending = version.submittedAt
      ? Math.floor(
          (Date.now() - new Date(version.submittedAt).getTime()) /
            (1000 * 60 * 60 * 24),
        )
      : REMINDER_DAYS;

    await createNotificationsForUsers({
      db,
      userIds: managers.map((m) => m.id),
      type: "ESTIMATE_APPROVAL_REMINDER",
      category: "REMINDER",
      priority: "HIGH",
      title: `Estimate awaiting approval: ${estimate.name} (v${version.versionNumber})`,
      body: `Estimate "${estimate.name}" version ${version.versionNumber} has been pending approval for ${daysPending} days.`,
      entityId: version.id,
      entityType: "estimate_approval_reminder",
      link: `/estimates/${estimate.id}`,
      channel: "in_app",
    });

    reminderCount++;
  }

  return reminderCount;
}
