import type { Prisma } from "@prisma/client";

// Leave-clash detection (Crewing-Implementation-Spec §5.3, R6 — Option A).
// Approving a leave is a clash when the remaining ACTIVE same-rank cover on the
// vessel over the leave window would fall BELOW the rank's required strength for
// that vessel (VesselRankRequirement.minStrength, default 1 when unconfigured).
// A clash auto-raises a LEAVE requisition.

interface ClashInput {
  assignmentId: string;
  rankId: string;
  vesselId: string | null;
  fromDate: Date;
  toDate: Date;
}

export async function leaveCausesClash(
  tx: Prisma.TransactionClient,
  { assignmentId, rankId, vesselId, fromDate, toDate }: ClashInput
): Promise<boolean> {
  // No vessel cost axis → no rank-cover check.
  if (!vesselId) return false;

  const requirement = await tx.vesselRankRequirement.findUnique({
    where: { vesselId_rankId: { vesselId, rankId } },
    select: { minStrength: true },
  });
  const requiredStrength = requirement?.minStrength ?? 1;
  if (requiredStrength <= 0) return false;

  // Other not-signed-off same-rank crew on the vessel (excludes the one going on leave).
  const others = await tx.crewAssignment.findMany({
    where: { rankId, vesselId, status: { not: "SIGNED_OFF" }, id: { not: assignmentId } },
    select: { id: true },
  });

  let remainingCover = 0;
  if (others.length > 0) {
    const otherIds = others.map((o) => o.id);
    const overlapping = await tx.leaveRequest.findMany({
      where: {
        assignmentId: { in: otherIds },
        status: "APPROVED",
        fromDate: { lte: toDate },
        toDate: { gte: fromDate },
      },
      select: { assignmentId: true },
    });
    const out = new Set(overlapping.map((l) => l.assignmentId));
    remainingCover = otherIds.filter((id) => !out.has(id)).length;
  }

  return remainingCover < requiredStrength;
}
